Reputation: 490
How does an instance of Enumerator
keep track of its internal state? Take the following code snippet for example:
enum = Enumerator.new do |yielder|
yielder << 1
yielder << 2
yielder << 3
end
puts enum.next # => 1
puts enum.next # => 2
enum.rewind # start again
puts enum.next # => 1
When an iterator method such as each
is called on enum
, it executes the block given to each
once for every call to yielder#<<
(or yielder#yield
).
What I'm trying to understand is how Ruby makes next
work. How does it remember the next
value? How does it rewind
back to the first one? If I were to code a basic implementation of how next
works in Ruby, how would I do it?
Upvotes: 2
Views: 77
Reputation: 211560
The Enumerator suspends execution internally and yields control to the caller. As Sergio says, it's fiber based, that is an execution unit more fine-grained than thread.
Fibers allow you do to this sort of thing:
def eat_more_fiber
puts "In"
Fiber.yield
puts "Out"
end
f = Fiber.new do
eat_more_fiber
end
f.resume
# Prints "In"
f.resume
# Prints "Out"
Note that after the first resume
call control goes back to that block of code.
Upvotes: 2