仮想的な無限列(10)
今回の主な修正点は…
- Callの中でlambdaを返すのは無駄なのでやめた。すぐ評価。
- Zipの定義にZipが出てきていたのをやめた。再帰呼び出しはCallで作る。
- シーケンスの頭に要素を逆詰めするUnshiftOfを作った。
- シーケンスのひながたOf...自体のシーケンスを作り、EachDoでそれぞれのひながたに特定のアクションを適用する練習。
class NilClass def to_s "_" end end Call = lambda {|f, *a| f[f, *a]} Sequence = lambda {|xs, *a| lambda {return a[0], Call[xs, *a]} } Zip = lambda {|op, s, t| Call[ lambda {|f, op, s, t| x, xs = s[] y, ys = t[] lambda { return op[x, y], f[f, op, xs, ys] } }, op, s, t ] } Walk = lambda {|n, xs, eachf, lastf| Call[ lambda {|fs, xs, n, eachf, lastf| if n > 0 y, ys = xs[] eachf[y, ys] Call[fs, ys, n - 1, eachf, lastf] else lastf[xs] end }, xs, n, eachf, lastf ] } Show = lambda {|xs| Walk[10, xs, lambda {|y, _| print "#{y}, "}, lambda {|_| puts "..." } ] } # Operators. Add = lambda {|x, y| x + y } Mul = lambda {|x, y| x * y } Power = lambda {|x, y| x ** y } # SequenceOf something. OfConstant = lambda {|s, *a| Sequence[s, a[0]]} OfNatural = lambda {|s, *a| Sequence[s, a[0] + 1]} OfFibonacci = lambda {|s, *a| Sequence[s, a[1], a[0] + a[1]]} OfGiven = lambda {|s, *a| Sequence[s, *a[1..-1]]} # Sequence -> Sequence ShiftOf = lambda {|s| x, xs = s[]; xs } UnshiftOf = lambda {|s, x| lambda {return x, s}} # Sequence -> Sequence DoubleOf = lambda {|s| Zip[Add, s, s]} PowerOf = lambda {|s| Zip[Power, s, Natural]} One = Sequence[OfConstant, 1] Two = Sequence[OfConstant, 2] Ten = Sequence[OfConstant, 10] Natural = Sequence[OfNatural, 0] NaturalPlus = ShiftOf[Natural] Fibonacci = Sequence[OfFibonacci, 0, 1] FibonacciOne = Zip[Add, Fibonacci, ShiftOf[Fibonacci]] Even = DoubleOf[Natural] Odd = Zip[Add, Even, One] Sample = Sequence[OfGiven, 3, 1, 4, 1, 5, 9] MinusSample = UnshiftOf[Sample, -1] PowerOfTwo = PowerOf[Two] PowerOfTen = PowerOf[Ten] puts "Sequence." Show[One] Show[Natural] Show[Fibonacci] Show[FibonacciOne] Show[NaturalPlus] Show[Even] Show[Odd] Show[Sample] Show[PowerOfTwo] Show[PowerOfTen] Show[MinusSample] puts "Meta sequence." SequenceOfOfs = Sequence[OfGiven, OfConstant, OfNatural, OfFibonacci, OfGiven] EachDo = lambda {|xs, action| Call[ lambda {|f, xs, action| y, ys = xs[] return unless y action[y] f[f, ys, action] }, xs, action ] } EachDo[SequenceOfOfs, lambda {|ofx| Show[Sequence[ofx, 0, 1, 2, 3]]}]
実行結果です。
Meta sequence.の後に、OfConstant, OfNatural, OfFibonacci, OfGivenの4個のひながたに対して0, 1, 2, 3を与えた場合の数列が4個表示されています。
Sequence. 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, 5, 8, 13, 21, 34, 55, 89, ... 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, ... 3, 1, 4, 1, 5, 9, _, _, _, _, ... 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, ... 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, ... -1, 3, 1, 4, 1, 5, 9, _, _, _, ... Meta sequence. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 0, 1, 2, 3, _, _, _, _, _, _, ...