仮想的な無限列(11)

今回の主な修正点は…

  • 累積的な処理を行うAccumulateWithを作成。
  • それを元にしてSumOfとProductOfを作成。
  • それを元にしてSumOfNaturalPlus, ProductOfNaturalPlusを作成。
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]]}]

puts "Accumulated sequence."

AccumulateWith = lambda {|op, xs, xm|
  Call[
    lambda {|f, op, xs, xm|
      y, ys = xs[]
      ym = op[xm, y]
      lambda { return ym, f[f, op, ys, ym] }
    }, op, xs, xm
  ]
}

SumOf = lambda {|xs| AccumulateWith[Add, xs, 0]}
ProductOf = lambda {|xs| AccumulateWith[Mul, xs, 1]}

SumOfNaturalPlus = SumOf[NaturalPlus]
ProductOfNaturalPlus = ProductOf[NaturalPlus]
Show[SumOfNaturalPlus]
Show[ProductOfNaturalPlus]

実行結果です。

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, _, _, _, _, _, _, ...
Accumulated sequence.
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, ...