Ruby中的懒惰斐波那契
我可以在Clojure中写一个懒惰的斐波那契,如下所示:
(def fib (lazy-cat [1 1] (map +' fib (rest fib))))
我正在尝试(不成功)在Ruby中编写它,如下所示:
fib = Enumerator.new do |yielder| yielder << 1 << 1 fib.zip(fib.drop(1)).map do |a,b| yielder << (a + b) end end
在简化的情况下,这适用:
fib = Enumerator.new do |yielder| yielder << 1 << 1 puts "here" end puts fib.take(2).inspect puts fib.drop(1).take(1).inspect
但这不是:
fib = Enumerator.new do |yielder| yielder << 1 << 1 puts "here" fib.drop(1) end puts fib.take(2).inspect puts fib.drop(1).take(1).inspect
为什么最后一个例子给我一个SystemStackError: stack level too deep
错误?
首先,ruby版本中的fib
不等同于clojure版本。 在clojure版本中,它是一个function。
除了明确指定它之外, Enumerable#drop
Enumerable#zip
, Enumerable#drop
和Enumerable.take
不是延迟的。 如果你不调用Enumerable#lazy
,它们会返回一个数组(急切地消耗所有项目;导致exception)。
def fib Enumerator.new do |yielder| yielder << 1 << 1 fib.lazy.zip(fib.lazy.drop(1)).each do |a,b| yielder << a + b end end end fib.take(2) # => [1, 1] fib.lazy.drop(1).take(1).to_a # Note: `lazy`, `to_a`. # => [1] fib.take(4) # => [1, 1, 2, 3]