Asad Moosvi
Asad Moosvi

Reputation: 490

How does an Enumerator object keep track of its state?

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

Answers (1)

tadman
tadman

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

Related Questions