仮想的な無限列(12)

今回の主な修正点は…

  • AccumulateWithの引数をfold風にした。
  • 念願のMapを作成。
  • 無意味な同一引数渡しを省略(op, eachfなど)。
  • Mapを使ってFibonacciの各項が偶数か奇数かを調べてみる。
Call = lambda {|f, *a| f[f, *a]}

Zip = lambda {|op, s, t|
  Call[
    lambda {|f, s, t|
      x, xs = s[]
      y, ys = t[]
      lambda { return op[x, y], f[f, xs, ys] }
    }, s, t
  ]
}

Sequence = lambda {|xs, *a|
  lambda { return a[0], Call[xs, *a] }
}

Walk = lambda {|n, xs, eachf, lastf, nilf|
  Call[
    lambda {|fs, xs, n|
      return lastf[xs] if n <= 0
      y, ys = xs[]
      return nilf[ys] if y.nil?
      eachf[y, ys]
      Call[fs, ys, n - 1]
    }, xs, n
  ]
}

Show = lambda {|xs|
  Walk[10, xs,
    lambda {|y, _| print "#{y}, "},
    lambda {|_| puts "..." },
    lambda {|_| puts "" }
  ]
}

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

Map = lambda {|op, xs|
  Call[
    lambda {|f, xs|
      y, ys = xs[]
      lambda { return op[y], f[f, ys] }
    }, xs
  ]
}

# Operators.
Add = lambda {|x, y| x + y }
Mul = lambda {|x, y| x * y }
Power = lambda {|x, y| x ** y }
IsEven = lambda {|x| x % 2 == 0}
Increment = lambda {|x| Add[x, 1]}
ParityChecker = lambda {|x| IsEven[x] ? "Even(#{x})" : "Odd(#{x})" }

# 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|
      y, ys = xs[]
      return unless y
      action[y]
      f[f, ys]
    }, xs
  ]
}

EachDo[SequenceOfOfs, lambda {|ofx| Show[Sequence[ofx, 0, 1, 2, 3]]}]

puts "Accumulated sequence."
SumOf = lambda {|xs| AccumulatedWith[Add, 0, xs]}
ProductOf = lambda {|xs| AccumulatedWith[Mul, 1, xs]}

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

puts "Maps."
Show[Map[Increment, Natural]]
Show[Map[ParityChecker, Fibonacci]]

実行結果です。

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, ...
Maps.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
Even(0), Odd(1), Odd(1), Even(2), Odd(3), Odd(5), Even(8), Odd(13), Odd(21), Even(34), ...