仮想的な無限列(3)

昨日の続きで、無限列を考えています。zipの意味を変えて少し整理しました。

class Sequence < Proc
  def self.create(*a, &block)
    self.new(&block).define(*a)
  end
  def define(*a)
    lambda { return a[0], self.call(self, *a) }
  end
end
class Proc
  def to_s(n=10)
    return "..." if n == 0
    x, xs = self.call()
    x.to_s + ", " + xs.to_s(n - 1)
  end
  def drop(n)
    return self if n == 0
    _, s = self.call()
    s.drop(n - 1)
  end
  def zip(s, t)
    x, xs = s.call()
    y, ys = t.call()
    lambda { return self.call(x, y), self.zip(xs, ys) }
  end
end

puts (Ones = Sequence.create(1) {|f, a| f.define(a) })
puts (Natural = Sequence.create(0) {|f, a| f.define(a + 1)})
puts (NaturalPlus = Natural.drop(1))
puts (Fibonacci = Sequence.create(1, 1) { |f, a, b| f.define(b, a + b) })

Add = lambda {|a, b| a + b}
puts (Evens = Add.zip(Natural, Natural))
puts (Odds = Add.zip(Evens, Ones))

実行結果です。

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, ...
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, ...

ああ楽しい。
追記:jitteさんからのご指摘で、constantのf.define(a, a)をf.define(a)に修正しました。