仮想的な無限列(8)

有限列も使えるようにしました。OfGivenを使います。

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]}
OfGiven = lambda {|s, *a| Sequence[s, *a[1..-1]]}

DoubleOf = lambda {|s| Zip[Add, s, s]}
ShiftOf = lambda {|s| DropFrom[s, 1]}
One = Sequence[OfConstant, 1]
Natural = Sequence[OfNatural, 0]
NaturalPlus = ShiftOf[Natural]
Fibonacci = Sequence[OfFibonacci, 0, 1]
Even = DoubleOf[Natural]
Odd = Zip[Add, Even, One]
Sample = Sequence[OfGiven, 3, 1, 4, 1, 5, 9]

Show[One]
Show[Natural]
Show[Fibonacci]
Show[NaturalPlus]
Show[Even]
Show[Odd]
Show[Sample]

実行結果です。

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, ...
3, 1, 4, 1, 5, 9, , , , , ...