在ruby docs我发现了这段代码:

fib = Enumerator.new do |y|
  a = b = 1
  loop do
    y << a
    a, b = b, a + b
  end
end

问题是我不明白它是干什么的。一般来说,它计算斐波那契数,但我很难理解细节。什么是y (Enumerator::Yielder)docs什么也没说。<<方法做什么?(我知道它的屈服别名)。为什么当y << a
被移除?谢谢!

最佳答案

请考虑以下代码:

fib = Enumerator.new do |y|
  puts "Enter enumerator"
  a = b = 1
  loop do
    puts "Inside loop"
    y << a
    puts "y: #{y.inspect}, a: #{a}, b: #{b}"
    a, b = b, a + b
  end
end
puts fib.take(5)

它打印:
# Enter enumerator
# Inside loop
# y: #<Enumerator::Yielder:0x000000059a27e8>, a: 1, b: 1
# Inside loop
# y: #<Enumerator::Yielder:0x000000059a27e8>, a: 1, b: 2
# Inside loop
# y: #<Enumerator::Yielder:0x000000059a27e8>, a: 2, b: 3
# Inside loop
# y: #<Enumerator::Yielder:0x000000059a27e8>, a: 3, b: 5
# Inside loop

# 1
# 1
# 2
# 3
# 5

显然,这个输出实际上给了你所有问题的提示。注意,我们只进过一次义长老。让我们深入了解一下:
为什么loop是无限的?
因为斐波那契数列是无穷的。此枚举器用于Enumerable#take(请参见上面的示例)。
什么是Enumerator::Yielder
这是一种抽象。它的方法实际上调用被调用方的块,将参数作为块参数传递。
yield方法的作用是什么?
屈服一次。换句话说,它调用调用者代码,将其参数传递给调用者的块。在这个特定的例子中,它将回调<<块,从each实例传递a作为块参数(正如我在这里命名的那样)。
为什么移除Yielder时会发生无限循环?
因为没有发生过。在我的示例中,被调用者在得到五次(5作为e的参数)后将停止。

09-25 16:20