仮想的な無限列(7)
Zipを作りました。それからarityや型的なものをちょっぴり名前に反映。OfNarutalとか。
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 "..." } ][] } DropFrom = lambda {|xs, n| Walk[n, xs, lambda {|y, ys|}, lambda {|ys| ys} ][] } Zip = lambda {|op, s, t| x, xs = s[] y, ys = t[] lambda { return op[x, y], Zip[op, xs, ys] } } Sequence = lambda {|s, *a| lambda { return a[0], s[s, *a] } } Add = lambda {|x, y| x + y } OfConstant = lambda {|s, a| Sequence[s, a]} OfNatural = lambda {|s, a| Sequence[s, a + 1]} OfFibonacci = lambda {|s, a, b| Sequence[s, b, a + b]} DoubleOf = lambda {|s| Zip[Add, s, s]} One = Sequence[OfConstant, 1] Natural = Sequence[OfNatural, 0] NaturalPlus = DropFrom[Natural, 1] Fibonacci = Sequence[OfFibonacci, 0, 1] Even = DoubleOf[Natural] Odd = Zip[Add, Even, One] Show[One] Show[Natural] Show[Fibonacci] Show[NaturalPlus] Show[Even] Show[Odd]
上のプログラムで、
Even = DoubleOf[Natural]
のあたりにぐっと来ませんか?
実行結果です。
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ... 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, ... 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, ...