仮想的な無限列(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, ...
本能のままに作っているので、おかしなところがあったら教えてください。