How does a Ruby Enumerator object iterate externally on top of an internal iterator?

According to the Ruby documentation, an Enumerator object uses a method each(for enumeration) if to_enumeither the method is enum_fornot specified for the target method. Now let's take the next monkey patch and its enumerator, as an example

o = Object.new
def o.each
    yield 1
    yield 2
    yield 3
end
e = o.to_enum

loop do
  puts e.next
end

Given that the Enumerator object uses the method eachto respond when called next, what does the method call look like eachevery time it is called next? Does the Enumeartor class preload all content o.eachand create a local copy for listing? Or is there some kind of Ruby magic that hangs in operations in each yield statement until nextcalled on enumeartor?

, ? -, ?

Ruby 1.9.2.

+5
1

, . , - , Fiber each . each, Fiber , , , Fiber.

, " " , , , #to_a . , , - .

C- Enumerator. Ruby, , :

class MyEnumerator
  def initialize(enumerable)
    @fiber = Fiber.new do
      enumerable.each { |item| Fiber.yield item }
    end
  end

  def next
    @fiber.resume || raise(StopIteration.new("iteration reached an end"))
  end
end

class MyEnumerable
  def each
    yield 1
    yield 2
    yield 3
  end
end

e = MyEnumerator.new(MyEnumerable.new)
puts e.next # => 1
puts e.next # => 2
puts e.next # => 3
puts e.next # => StopIteration is raised
+8

All Articles