In Ruby, Enumerable
is a module that allows us to access each element out of a collection, one at a time. It is used as a mix-in for various classes that contain multiple elements, such as Array
s, Hash
es, and Range
s. If we think of enumerable as an adjective, then Enumerator
is the noun form. It is a method object (a noun that performs a verb), a tool we can use to enumerate an action, one at a time, on every element of another object. For now, we will focus on one such enumerator: the map
method.
Enumerable#map
is an enumerator that returns a new array in which each index is the result of performing the block one time on each element in a collection. For example:
(1..5).map { |i| i * i }
=> [1, 4, 9, 16, 25]The block (in curly brackets) directed this
map
method to take each element of the range 1 - 5 (inclusive) and multiply the element by itself. The result is an array containing a list of the first five perfect squares. It is important to note, however, that if the action in the block does not have a return value, the array created will have a nil
value in each index. For example, the print
method will print a string to the console, but does not return any value. So, if we wanted to print each element in our range with a space in between, we might do so thusly:
(1..5).map { |i| print i.to_s + ' ' }
=> 1 2 3 4 5 => [nil, nil, nil, nil, nil]Let's talk a little bit about what went on here. The block instructs our
map
method to take each element in the range and print that element (converted to a string) and add a space afterward. The print
method does not create a line break, so each of our elements (as well as the next line in the terminal) all get printed to one line. The next piece is the array that got returned. Each time we printed an element, the nil
value was returned in our array. This is why we see nil
five times, one for each element of the range.
It is also important to note that if no block is given, the return is an enumerator object. For example:
(1..5).map
=> <Enumerator: 1..5:map>Thus, we can later determine what this enumerator will do. For example, we will create an enumerator called
enum
:
enum = (1..5).map
=> <Enumerator: 1..5:map>
example.map { |i| i + 1 }
=> [2, 3, 4, 5, 6]After the enumerator was created, we are able to apply the
map
block with new content. In this case, we added 1 to each element.
Well, this has been just a small look into one thing that enumerators can do. I hope it has piqued your interest and that you will investigate enumerator methods further, as I will. Please check in again as I continue my journey into web development. I will continue to post about my learnings along the way. And, for your sake and mine, I'm going to resist the map pun here. Until next time, happy coding!