# Enumerators

An Enumerator (opens new window) is an object that implements iteration in a controlled fashion.

Instead of looping until some condition is satisfied, the object enumerates values as needed. Execution of the loop is paused until the next value is requested by the owner of the object.

Enumerators make infinite streams of values possible.

# Custom enumerators

Let's create an Enumerator (opens new window) for Fibonacci numbers (opens new window).

fibonacci = Enumerator.new do |yielder|
  a = b = 1
  loop do
    yielder << a
    a, b = b, a + b
  end
end

We can now use any Enumerable (opens new window) method with fibonacci:

fibonacci.take 10
# => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

# Existing methods

If an iteration method such as each is called without a block, an Enumerator (opens new window) should be returned.

This can be done using the enum_for (opens new window) method:

def each
  return enum_for :each unless block_given?

  yield :x
  yield :y
  yield :z
end

This enables the programmer to compose Enumerable (opens new window) operations:

each.drop(2).map(&:upcase).first
# => :Z

# Rewinding

Use rewind (opens new window) to restart the enumerator.

= Enumerator.new do |yielder|
  x = 0
  loop do
    yielder << x
    x += 1
  end
end.next
# => 0.next
# => 1.next
# => 2.rewind

ℕ.next
# => 0

# Parameters

Parameter Details
yield Responds to yield, which is aliased as <<. Yielding to this object implements iteration.