问题描述
我可以像这样在Clojure中写一个懒惰的斐波那契:
I can write a lazy fibonacci in Clojure like this:
(def fib (lazy-cat [1 1] (map +' fib (rest fib))))
并且我正在尝试(未成功)用Ruby这样编写代码:
and I'm trying (unsuccessfully) to write it in Ruby like this:
fib = Enumerator.new do |yielder|
yielder << 1 << 1
fib.zip(fib.drop(1)).map do |a,b|
yielder << (a + b)
end
end
在简化的情况下,这可行:
In the simplified case, this works:
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
错误?
Why does that last example give me a SystemStackError: stack level too deep
error?
推荐答案
首先,红宝石版本中的fib
不等同于clojure版本.在clojure版本中,它是一个函数.
First, fib
in the ruby version is not equivalent to the clojure version. In clojure version, it's a function.
和 Enumerable#zip
, Enumerable#drop
和 Enumerable.take
并不懒惰,除非您明确指定.如果您不拨打 Enumerable#lazy
,则它们会返回一个数组(急于消耗所有物品;导致异常).
And Enumerable#zip
, Enumerable#drop
and Enumerable.take
are not lazy unless you explicitly specify it. If you don't call Enumerable#lazy
, they return an Array (eagerly consuming all items; cause the 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]
这篇关于Ruby中的惰性斐波那契的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!