仮想的な無限列(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, _, _, _, _, _, _, ...