In the Ruby Array Class documentation, I often find:
If no block is given, an enumerator is returned instead.
Why would I not pass a block to #map
? What would be the use of my doing just:
[1,2,3,4].map
instead of doing:
[1,2,3,4].map{ |e| e * 10 } # => [10, 20, 30, 40]
Can someone show me a very practical example of using this enumerator?
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 anEnumerator
can be infinite. You cannot have anArray
of all even numbers or a stream of zeroes or all prime numbers, but you can definitely have such anEnumerator
: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)