Better X by learning Y
(or, how I learned what enumerators are for)
The Enumerable1 module is one of the most used in Ruby. I often read its docs to see what methods are available and how they’re used. One phrase that jumped out at me when I first started Ruby was
If no block is given, an enumerator is returned instead.
This shows up in various forms in a lot of the method descriptions. According to the docs Enumerator2 is
A class which allows both internal and external iteration.
I was puzzled. Calling, say, each_with_index
without a block argument returned an enumerator which I could then later iterate over. I thought, why not just pass the block in the first place and be done with it? I filed the question away in my head.
Some two years later I took Peter Norvig’s Design of Computer Programs class on Udacity3. There I encountered Python’s awesome generators and iterators. I’m not going to go into detail here, I’ll just say that these tools allow lazy evaluation of collection4 items, which means you don’t have to load the entire collection all at once.
I found this very exciting, but for some reason I didn’t make the connection to Ruby’s Enumerator. The ‘a-ha!’ moment came only after I did a search for ‘Ruby lazy evaluation’.
I’ve always believed that studying languages other than your ‘main’ one makes you a better programmer, but in this case I especially like how I learned how to use a language feature by seeing it in another language.
If you’re curious about enumerators and generators here are a few links to check out:
How to use an enumerator (Stack Overflow question)
Ruby 2.0 Works Hard So You Can Be Lazy
What can you use Python generator functions for? (Stack Overflow question)
Generator Tricks for Systems Programmers
Why, sometimes I’ve believed as many as six impossible things before breakfast.
– The White Queen in Through the Looking-Glass by Lewis Carroll
-
Lists, arrays, etc., not the Python collection module ↩