This repo is for my own personal practice of making ruby enumerators. There are several enumerable examples.
I used these resources for help:
Returning enumerators from methods allows more control over collections. It's more efficient to return an enumerator as you can take the elements from the collection as you like. You do not have to take the entire collection.
There are three ways to create an enumerator:
- Kernel#to_enum
- Kernel#enum_for
- Enumerator.new
def muppets
Enumerator.new do |yielder|
yielder.yield 'Animal'
yielder.yield 'Kermit'
yielder.yield 'Piggy'
yielder.yield 'Fuzzy Bear'
end
end
muppets_enum = muppets
muppets_enum.entries # => ["Animal", "Kermit", "Piggy", "Fuzzy Bear"]
This is a basic enumerator that returns an enumerable collection of muppets. What is happening is an instance of enumerator is created which will have all of the enumerator methods. I have manually defined in this enumerator that the yielder will yield a 4 differnt muppets as the enumerator is traversed.
muppet_enum.entries
Goes through the enumerator yielding them and collecting
them in an array.
However you can choose to yield only the elements that you want from your
enumerator. Here we can call next on the enumerator which yields the next
element until the enumerator ends.
muppets_enum.next
=> "Animal"
muppets_enum.next
=> "Kermit"
muppets_enum.next
=> "Piggy"
muppets_enum.next
=> "Fuzzy Bear"
muppets_enum.next
=> StopIteration: iteration reached an end
A StopIteration
error is received when the enumerator has yielded all it's
elements.
A benefit of this approach is enumerators can be returned that have infinite elements however you can take as need and the enumerator will only yield the parts it requires.
def even_numbers
return enum_for(:numbers) unless block_given?
number = 2
loop do
yield number
number += 2
end
end
This method will return an infinite enumerator of even numbers. If you want the first 10 even numbers rather than creating an never array that calculates all numbers you can take the elements as you require from the enumerator.
even_numbers.take(10)
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]