仮想的な無限列(2)

昨日の続きで、仮想的な無限列を作っております。とりあえず、こんなのできましたというご紹介を。

  • Sequenceクラスは、初期値が与えられれば無限列を作るひながたを表すクラスです。
  • そしてSequence#defineで初期値を与えると実際の無限列が作られます。
  • 無限列は実際にはProcのインスタンスで、具体的な数列を得たかったら、x, xs = xs.call()を繰り返します。(to_s参照)
  • これらのクラスには、インスタンス変数が一個もなく、変数への再代入もなく、再帰以外のループもありません。
  • (あとは、dropやzipの再帰呼び出しで名前を消せればよいんですね<なにがよいのかよくわからないが)
class Sequence < Proc
  def car(*a)
    a[0]
  end
  def cdr(*a)
    call(self, *a)
  end
  def define(*a)
    lambda { return self.car(*a), self.cdr(*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(op, other)
    x, xs = self.call()
    y, ys = other.call()
    lambda { return op.call(x, y), xs.zip(op, ys) }
  end
end

# Constant numbers.
constant = Sequence.new { |f, a| f.define(a) }

# Constant 1.
allone = constant.define(1)
puts allone
#=> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...

# Natural numbers, starting at 0.
natural = Sequence.new {|f, a| f.define(a + 1)}
puts natural.define(0)
#=> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...

# Fibonacci numbers, starting at 0, 1.
fibonacci = Sequence.new { |f, a, b| f.define(b, a + b) }
puts fibonacci.define(0, 1)
#=> 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

# Natural numbers, starting at 1.
puts natural.define(0).drop(1)
#=> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...

# Fibonacci numbers, starting at 1, 1.
puts fibonacci.define(0, 1).drop(1)
#=> 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

# Even numbers.
adder = lambda {|a, b| a + b }
even = natural.define(0).zip(adder, natural.define(0))
puts even
#=> 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, ...

# Odd numbers.
odd = even.zip(adder, allone)
puts odd
#=> 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, ...

# Fibonacci numbers, starting at 1, 2.
puts fibonacci.define(0, 1).zip(adder, fibonacci.define(0, 1).drop(1))
#=> 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

本能のままに作っているので、おかしなところがあったら教えてください。