仮想的な無限列(4)

仮想的な無限列シリーズです。オブジェクト指向ベースではなく、関数ベースを試してみます。

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

Show = lambda {|xs|
  SelfCall.call(
    lambda {|f, xs, n|
      if n == 0
        puts "..."
      else
        y, ys = xs.call()
        print "#{y}, "
        f.call(f, ys, n - 1)
      end
    }, xs, 10
  ).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))

Drop = lambda {|xs, n|
  SelfCall.call(
    lambda {|f, xs, n|
      if n == 0
        xs
      else
        y, ys = xs.call()
        f.call(f, ys, n - 1)
      end
    }, xs, n
  ).call()
}

NaturalPlus = Drop.call(Sequence.call(Natural, 0), 1)
Show.call(NaturalPlus)

実行結果です。順番に定数列、0オリジンの自然数、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, ...