The main distinction between an Enumerator
and most† other data structures in the Ruby core library (Array
, Hash
) and standard library (Set
, SortedSet
) is that an Enumerator
can be infinite. You cannot have an Array
of all even numbers or a stream of zeroes or all prime numbers, but you can definitely have such an Enumerator
:
evens = Enumerator.new do |y|
i = -2
y << i += 2 while true
end
evens.take(10)
# => [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
zeroes = [0].cycle
zeroes.take(10)
# => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
So, what can you do with such an Enumerator
? Well, three things, basically.
Enumerator
mixes inEnumerable
. Therefore, you can use allEnumerable
methods such asmap
,inject
,all?
,any?
,none?
,select
,reject
and so forth. Just be aware that anEnumerator
may be infinite whereasmap
returns anArray
, so trying tomap
an infiniteEnumerator
may create an infinitely largeArray
and take an infinite amount of time.There are wrapping methods which somehow "enrich" an
Enumerator
and return a newEnumerator
. For example,Enumerator#with_index
adds a "loop counter" to the block andEnumerator#with_object
adds a memo object.You can use an
Enumerator
just like you would use it in other languages for external iteration by using theEnumerator#next
method which will give you either the next value (and move theEnumerator
forward) orraise
aStopIteration
exception if theEnumerator
is finite and you have reached the end.
† Eg., an infinite range: (1..1.0/0)