本文介绍了Ruby中的惰性斐波那契的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以像这样在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中的惰性斐波那契的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-19 05:10