Reputation: 2103
At ruby docs I found this piece of code:
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
Thing is i cant understand what it does. In general it calculates fibonacci's numbers, but I have hard time understanding the details. What is y (Enumerator::Yielder)
? The docs says nothing about it. What does <<
method do? (I know its yield alias). Why does infinite loop happen when y << a
is removed?Thanks!
Upvotes: 5
Views: 1977
Reputation: 121000
Consider the following code:
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)
It prints:
# 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
Apparently, this output actually gives hints on all the question you’ve stated. Note, that we entered a yielder only once. Let’s dig into:
loop
is infinite?Because Fibonacci’s number sequence is infinite. This enumerator is intended to be used with Enumerable#take
(see an example above.)
Enumerator::Yielder
?It is an abstraction. It’s method yield
actually calls back the block of callee, passing a parameter as block parameters.
<<
method does?Yields once. In other words, it calls back the caller code, passing it’s parameter to the caller’s block. In this particular example, it will call back each
block, passing a
from Yielder
instance as block parameter (e
as I named it there.)
y << a
is removed?Because there are no yield
s happened. In my example, the callee will stop after yielding five (5 as parameter of take
) times.
Upvotes: 5