Ruby's magical Enumerable module
Tags: ruby, learning, enumerable
Published: 2018-05-29 13:46:31

---
title: Ruby's magical Enumerable module
layout: layout_ruby_magic
description: Ruby's handling of enumerables is one of it's most magical features. In this episode of Ruby Magic, we'll learn how these work and how to make your own objects tenumerable.
tags: ruby, learning, enumerable
cover_image: https://blog.appsignal.com/images/blog/2018-05/enumerable.jpg
canonical_url: https://blog.appsignal.com/2018/05/29/ruby-magic-enumerable-and-enumerator.html
published: true
---

It's time for another episode of [Ruby Magic](https://blog.appsignal.com/category/ruby-magic.html?utm_source=DevTo&utm_medium=DevToBlogPost&utm_campaign=DevToContentPosting_Enumerable)! This time, we'll look at one of Ruby's most magical features, which provides most of the methods you'll use when working with Ruby's enumerable classes like `Array`, `Hash` and `Range`. In the process, we'll learn what you can do with enumerable objects, how enumeration works, and how to make an object enumerable by implementing a single method.

## `Enumerable`, `#each` and `Enumerator`

*Enumeration* refers to traversing over objects. In Ruby, we call an object *enumerable* when it describes a set of items and a method to loop over each of them.

The built-in enumerables get their enumeration features by including the `Enumerable` module, which provides methods like `#include?`, `#count`, `#map`, `#select` and `#uniq`, amongst others. Most of the methods associated with arrays and hashes aren't actually implemented in these classes themselves, they're included.

*Note*: Some methods, like `#count` and `#take` on the `Array` class, *are* implemented specifically for arrays instead of using the ones from the `Enumerable` module. That's usually done to make operation faster.

The [`Enumerable` module](http://ruby-doc.org/core-2.5.1/Enumerable.html) relies on a method named `#each`, which needs to be implemented in any class it's included in. When called with a block on an array, the `#each` method will execute the block for each of the array's elements.

``` irb
irb> [1,2,3].each { |i| puts "* #{i}" }
* 1
* 2
* 3
=> [1,2,3]
```

If we call the `#each` method on an array *without* passing a block to execute for each of its elements, we'll receive an instance of `Enumerator`.

``` irb
irb> [1,2,3].each
=> #<Enumerator: [1, 2, 3]:each>
```

Instances of `Enumerator` describe how to iterate over an object. Enumerators [iterate over objects manually](https://ruby-doc.org/core-2.5.1/Enumerator.html#method-i-next) and chain enumeration.

``` irb
irb> %w(dog cat mouse).each.with_index { |a, i| puts "#{a} is at position #{i}" }
dog is at position 0
cat is at position 1
mouse is at position 2
=> ["dog", "cat", "mouse"]
```

The `#with_index` method is a good example of how changed enumerators work. In this example, `#each` is called on the array to return an enumerator. Then, `#with_index` is called to add indices to each of the array's elements to allow printing each element's index.

## Making objects enumerable

Under the hood, methods like `#max`, `#map` and `#take` rely on the `#each` method to function.

``` ruby
def max
  max = nil

  each do |item|
    if !max || item > max
      max = item
    end
  end

  max
end
```

Internally, `Enumerable`'s methods have C implementations, but the example above roughly shows how `#max` works. By using `#each` to loop over all values and remembering the highest, it returns the maximum value.

``` ruby
def map(&block)
  new_list = []

  each do |item|
    new_list << block.call(item)
  end

  new_list
end
```

The `#map` function calls the passed block with each item and puts the result into a new list to return after looping over all values.

Since all methods in `Enumerable` use the `#each` method to some extent, our first step in making a custom class enumerable is implementing the `#each` method.

## Implementing `#each`

By implementing the `#each` function and including the `Enumerable` module in a class, it becomes enumerable and receives methods like `#min`, `#take` and `#inject` for free.

Although most situations allow falling back to an existing object like an array and calling the `#each` method on that, let's look at an example where we have to write it ourselves from scratch. In this example, we'll implement `#each` on a *linked list* to make it enumerable.

### Linked lists: lists without arrays
  <p>A <a href="https://en.wikipedia.org/wiki/Linked_list">linked list</a> is a collection of data elements, in which each element points to the next. Each element in the list has two values, named the <em>head</em> and the <em>tail</em>. The head holds the element’s value, and the tail is a link to the rest of the list.</p>

  <pre><code>[42, [12, [73, nil]]</code></pre>

  <p>For a linked list with three values (42, 12 and 73), the first element’s head is 42, and the tail is a link to the second element. The second element’s head is 12, and the tail holds the third element. The third element’s head is 73, and the tail is <code>nil</code>, which indicates the end of the list.</p>

In Ruby, a linked list can be created by using a class that holds two instance variables named `@head` and `@tail`.

``` ruby
class LinkedList
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end

  def <<(item)
    LinkedList.new(item, self)
  end

  def inspect
    [@head, @tail].inspect
  end
end
```

The `#<<` method is used to add new values to the list, which works by returning a new list with the passed value as the head, and the previous list as the tail.

In this example, the `#inspect` method is added so we can see into the list to check which elements it contains.

``` irb
irb> LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
```

Now that we have a linked list, let's implement `#each` on it. The `#each` function takes a block and executes it for each value in the object. When implementing it on our linked list, we can use the list's recursive nature to our advantage by calling the passed block on the list's `@head`, and calling `#each` on the `@tail`, if it exists.

``` ruby
class LinkedList
  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end

  def <<(item)
    LinkedList.new(item, self)
  end

  def inspect
    [@head, @tail].inspect
  end

  def each(&block)
    block.call(@head)
    @tail.each(&block) if @tail
  end
end
```

When calling `#each` on an instance of our linked list, it calls the passed block with current `@head`. Then, it calls each on the linked list in `@tail` unless the tail is `nil`.

``` irb
irb> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb> list.each { |item| puts item }
42
12
73
=> nil
```

Now that our linked list responds to `#each`, we can `include Enumberable` to make our list enumerable.

``` ruby
class LinkedList
  include Enumerable

  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end

  def <<(item)
    LinkedList.new(item, self)
  end

  def inspect
    [@head, @tail].inspect
  end

  def each(&block)
    block.call(@head)
    @tail.each(&block) if @tail
  end
end
```

``` irb
irb> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb(main):003:0> list.count
=> 3
irb> list.max
=> 73
irb> list.map { |item| item * item }
=> [1764, 144, 5329]
irb> list.select(&:even?)
=> [42, 12]
```

## Returning `Enumerator` instances

We can now loop over all values in our linked list, but we can't chain enumerable functions yet. To do that, we'll need to return an `Enumerator` instance when our `#each` function is called without a block.

``` ruby
class LinkedList
  include Enumerable

  def initialize(head, tail = nil)
    @head, @tail = head, tail
  end

  def <<(item)
    LinkedList.new(item, self)
  end

  def inspect
    [@head, @tail].inspect
  end

  def each(&block)
    if block_given?
      block.call(@head)
      @tail.each(&block) if @tail
    else
      to_enum(:each)
    end
  end
end
```

To wrap an object in an enumerator, we call the `#to_enum` method on it. We pass `:each`, as that's the method the enumerator should be using internally.

Now, calling our `#each` method without a block will allow us to chain enumeration.

``` irb
irb(main):226:0> list = LinkedList.new(73) << 12 << 42
=> [42, [12, [73, nil]]]
irb(main):227:0> list.each
=> #<Enumerator: [42, [12, [73, nil]]]:each>
irb(main):228:0> list.map.with_index.to_h
=> {42=>0, 12=>1, 73=>2}
```

## Nine lines of code and an include

By implementing `#each` using the `Enumerable` module and returning `Enumerator` objects from our own, we were able to supercharge our linked list by adding nine lines of code and an include.

This concludes our overview of enumerables in Ruby. If you liked this article, check out the entire series on [Ruby Magic] ( https://blog.appsignal.com/category/ruby-magic.html?utm_source=DevTo&utm_medium=DevToBlogPost&utm_campaign=DevToContentPosting_Enumerable ). Magicians never share their secrets. But we do. 

We'd love to know what you thought of this article, or if you have any questions. We're always on the lookout for topics to investigate and explain, so if there's anything magical in Ruby you'd like to read about, don't hesitate to leave a comment.