在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
的参数)后将停止。