仮想的な無限列(5)

仮想的な無限列(4)では、ShowとDropが似ていたので、無限列のはじめからn歩あるくWalkを作って統合しました。

Call = lambda {|f, *a|
  lambda { f.call(f, *a) }
}

Walk = lambda {|n, xs, eachf, lastf|
  Call.call(
    lambda {|fs, xs, n, eachf, lastf|
      if n > 0
        y, ys = xs.call()
        eachf.call(y, ys)
        fs.call(fs, ys, n - 1, eachf, lastf)
      else
        lastf.call(xs)
      end
    }, xs, n, eachf, lastf
  )
}

Show = lambda {|xs|
  Walk.call(10, xs,
    lambda {|y, ys| print "#{y}, "},
    lambda {|ys| puts "..." }
  ).call()
}

Drop = lambda {|xs, n|
  Walk.call(n, xs,
    lambda {|y, ys|},
    lambda {|ys| ys}
  ).call()
}

Sequence = lambda {|f, *a|
  lambda { return a[0], f.call(f, *a) }
}

Constant = lambda {|f, a| Sequence.call(f, a)}
Natural = lambda {|f, a| Sequence.call(f, a + 1)}
Fibonacci = lambda {|f, a, b| Sequence.call(f, b, a + b)}

Show.call(Sequence.call(Constant, 1))
Show.call(Sequence.call(Natural, 0))
Show.call(Sequence.call(Fibonacci, 0, 1))
Show.call(Drop.call(Sequence.call(Natural, 0), 1))

実行結果です。

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, ...