Last active
April 16, 2020 15:44
-
-
Save TayKangSheng/70a1574175dade1d6c84d918693dabe5 to your computer and use it in GitHub Desktop.
How to create your own Ruby Enumerator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Enumerator is a very powerful feature if you know how to use it. The most | |
| # powerful part of Enumerator is the possibility of chaining them. Take some | |
| # time to understand the intricacies of it because it is not very well | |
| # documented. Some awesome references that I found are listed below. Note that | |
| # I didn't understand when reading any of them right off the bat. Read a few, | |
| # dig some documentation and experiment for yourself to get the "fuller" | |
| # picture. | |
| # | |
| # [1]: https://blog.arkency.com/2014/01/ruby-to-enum-for-enumerator/ | |
| # [2]: https://stackoverflow.com/a/9194052 | |
| # [3]: https://ruby-doc.org/core-2.7.1/Enumerator.html | |
| class MyClass | |
| def an_iterator | |
| # enum_for and to_enum is the same. [1] | |
| return enum_for(:an_iterator) if not block_given? | |
| # Use of yield here is of utmost importance, any code from here on will be | |
| # executed by the enumerator over and over again. | |
| index = 0 | |
| while index <= 10 | |
| yield(index += 2) | |
| end | |
| end | |
| def an_iterator_but_doesnt_have_yield | |
| return enum_for(:an_iterator_but_doesnt_have_yield) if not block_given? | |
| end | |
| end | |
| my_class = MyClass.new | |
| ################ | |
| #### Example of using an enumerator | |
| ################ | |
| ## Without block | |
| iterator1 = my_class.an_iterator # returns you an iterator. | |
| puts iterator1.take(5) | |
| # => [2, 4, 6, 8, 10] | |
| puts iterator1.next | |
| # => 12 | |
| ## With block | |
| iterator2 = my_class.an_iterator # returns you an iterator. | |
| iterator2.each do |x| | |
| # #each returns another enumerator enumerating #an_iterator method. x is what | |
| # is yielded when calling #next on iterator 2. | |
| puts x | |
| end | |
| # 2 | |
| # 4 | |
| # 6 | |
| # 8 | |
| # 10 | |
| # => nil | |
| ################ | |
| #### Example of using an iterator that does not have yield | |
| ################ | |
| ## Without block | |
| missing_yield_iterator1 = my_class.an_iterator_but_doesnt_have_yield | |
| puts missing_yield_iterator1.take(10) | |
| # [] | |
| puts missing_yield_iterator1.next | |
| # StopIteration: iteration reached an end | |
| ## With block | |
| missing_yield_iterator2 = my_class.an_iterator_but_doesnt_have_yield | |
| missing_yield_iterator2.each do |x| | |
| puts x | |
| end | |
| # => nil |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment