Enumerator is used for iterating over a collection of items. It allows both internal and external iteration.
So how do we Create an Enumerator?
There are 3 different ways to create it. They are from,- A Block,
- An Enumerable,
- A Blockless Enumerable Method Call.
From a Block
We can create an enum by passing a block to its constructor. A yielder object will be passed to this block. The yielder’s#<< method can be used to define the elements. Enumerator#next can then be used to provide iteration.
Eg:
enum = Enumerator.new do |yielder| yielder << "Red" yielder << "Panthers" end enum.next # "Red" # StopIteration: when it reached an end
From an Enumerable
The most common way to create anEnumerator is from an Enumerable object, specifically, an object that defines a #each method. Object#to_enum is implemented to return a new Enumerator which will enumerate by sending #each to its receiver.
Eg:
array = [1, 2, 3]
enum = array.to_enum
enum.each {|n| n * 2} # 2 4 6
From a Blockless Enumerable Method Call
There are severalEnumerable methods that take a block and returns an Enumerator when called without a block. For instance, calling Array#select without a block will return an Enumerator with an #each method that will filter like #select.These blockless calls offer a concise alternative to Object#to_enum.
Eg:
array = [1, 2, 3, 4]
enum = array.select
enum.each {|n| n % 2 == 0} # [2, 4]
When do we use an Enumerator?
We can use this type instead of defining many constants for fields (such as astatus).For example, status can have values active and inactive in different condition. So that, we can use this type as below:
Eg:
status =%w(active inactive).each puts status.class # => Enumerator puts status.next # => active puts status.next # => inactive puts status.next # raises StopIterationSo by using it, we can simplify our code as above.
Why are they so special?
Well,
- It provides enumeration functionality to objects without it.
- You can control the iteration process in an efficient way using different methods like .each, .select, .next, .peek etc.
- There is a feature called Lazy enumerator, which will prevent iterate over an infinite collection.
- It saves a lot of typing(see above example), which makes the programmer more efficient.
