仮想的な無限列(6)

リファレンスri Proc#callを見ていて、f.call(1, 2, 3)の代わりにf[1, 2, 3]が使えることを知りました。すばらしい。

Call = lambda {|f, *a|
  lambda { f[f, *a] }
}

Walk = lambda {|n, xs, eachf, lastf|
  Call[
    lambda {|fs, xs, n, eachf, lastf|
      if n > 0
        y, ys = xs[]
        eachf[y, ys]
        fs[fs, ys, n - 1, eachf, lastf]
      else
        lastf[xs]
      end
    }, xs, n, eachf, lastf
  ]
}

Show = lambda {|xs|
  Walk[10, xs,
    lambda {|y, ys| print "#{y}, "},
    lambda {|ys| puts "..." }
  ][]
}

Drop = lambda {|xs, n|
  Walk[n, xs,
    lambda {|y, ys|},
    lambda {|ys| ys}
  ][]
}

Sequence = lambda {|f, *a|
  lambda { return a[0], f[f, *a] }
}

Constant = lambda {|f, a| Sequence[f, a]}
Natural = lambda {|f, a| Sequence[f, a + 1]}
Fibonacci = lambda {|f, a, b| Sequence[f, b, a + b]}

Show[Sequence[Constant, 1]]
Show[Sequence[Natural, 0]]
Show[Sequence[Fibonacci, 0, 1]]
Show[Drop[Sequence[Natural, 0], 1]]