# Making an Enumerable

> Last updated: 2017-06-08

A couple of weeks ago I wrote about [some of the handy methods](http://www.thagomizer.com/blog/2017/04/20/your-friend-enumerable.html) that are part of the Enumerable module in Ruby. This week I thought I would talk about how you can create a class that has all these handy methods by using the Enumerable mixin in your class.

## Linked Lists

I wrote a simple [linked list](https://en.wikipedia.org/wiki/Linked_list) class to use as a demonstration. Linked lists are a chain of objects, usually called nodes. Each node points to the node after it. Here’s a picture where the nodes are represented as sets of two boxes. The first box in each pair holds the value. The second box points to the node after it. A box with a slash through it has value `nil`.

![Linked list diagram for 7, 12, and 8](/img/LinkedList.jpg)

If it helps think about a linked list as being a set of clues in a treasure hunt. You start at one clue, it has some value and points you to the next clue, and so on until you get to the end. My node class looks like this:

```
class Node
  attr_accessor :value, :next

  def initialize value
    @value = value
    @next = nil
  end
end
```

Each node has a value. The initialize method sets the value when it creates a new node. Nodes also have a value called next which is the next node in the chain. New nodes have next set to nil since they are at the end of the chain.

The linked list class itself has two instance variables: head and tail. Head is the first value in the chain. Tail is the last value in the chain. There are also two methods `push` and `pop`. My implementation is a [queue](http://www.thagomizer.com/blog/2016/05/06/algorithms-queues-and-stacks.html), so push adds the new value to the end, and pop removes a value at the beginning of the linked list.

```
class LinkedList
  attr_accessor :head, :tail

  def initialize
    @head = nil
    @tail = nil
  end

  def push value
    n = Node.new value

    if @tail
      @tail.next = n
    else
      @head = n
    end

    @tail = n
  end

  def pop
    raise "Empty List" unless @head
    v = @head.value
    @head = @head.next
    v
  end
end
```

This is a basic implementation. Some edge cases are not covered, but this is sufficient to demo enumerable.

## The Enumerable Module

Enumerable is a module in the Ruby Standard Library. That sentence contains a lot of technical jargon, but it means that Enumerable is a set of functionality that works on almost any collection. Hash, Array, and Range include Enumerable which is why methods like `all?` and `each_cons` work on all of them. Enumerable is also included in classes like `Dir` and `IO` allowing you to use methods like `reject` on collections of files or on file contents.

To include Enumerable in your class, you must implement `each` and put `include Enumerable` in the class definition. The `each` method must take a block and call that block for each successive element in the collection. For directories, that might mean each file the directory contains. For a range, each calls the block with each successive integer. Here’s the implementation of `each` for the linked list class.

```
def each
  node = @head

  while node do
    yield node
    node = node.next
  end
end
```

The `each` method first gets the head node, calls the block passing that node in using yield, and then sets node to the next node before looping. The last node always has `nil` as the next value, so the while condition ensures the loop stops once we have hit the end of the chain. That is all that you need to add all the methods of Enumerable in your class.

I can run `each_with_index` on my linked list. I can use `each_cons` and `each_slice`. I can call `minmax` on a linked list and get the minimum and maximum values stored in that list. I can even use one of my favorite methods, `zip`, to interleave values from a linked list with values in another linked list or another collection class altogether.

## When To Mixin Enumerable

As you have seen, it is easy to make a class enumerable. However, just because you can doesn’t mean you should. You should only include Enumerable if your class _is_ a collection, not when it _has_ a collection. For example, a classroom class will have a collection of students. It also will probably have attributes for the teacher’s name, the location, meeting, and a subject or grade. While it would be handy to call `classroom.each` to iterate through the students, it is bad design to do so. You want to iterate through the students so `classroom.students.each` is more accurate and will lead to more maintainable code in the long term.

As a comparison, if you were implementing a RecordSet class to represent rows of a database it might make sense to include Enumerable. In this case, the class is a kind of collection. It probably doesn’t have any additional attributes beyond the data. Since it is a collection that you can enumerate, it makes sense to include Enumerable. If you are having problems telling the difference between these cases, look to see what additional attributes are in the class. If there are several attributes in addition to the collection or data, then it probably isn’t a good idea to include Enumerable. If the primary attribute is the collection then including Enumerable may make sense.

Please enable JavaScript to view the [comments powered by Disqus.](https://disqus.com/?ref_noscript)

 ![Aja Hammerly](/img/traditionalheadshot.jpg)

Aja Hammerly

Seattle, WA

### library\_books Series Index 

- [Developer Relations](/series#developer-relations)4
- [Machine Learning Basics](/series#machine-learning-basics)3
- [Battleship](/series#battleship)5
- [Talks I Love](/series#talks-i-love)6
- [Algorithms with Auntie Aja](/series#algorithms-with-auntie-aja)3
- [Ruby and GCP](/series#ruby-and-gcp)5
- [Playing with Data](/series#playing-with-data)3
- [Kubernetes & Rails](/series#kubernetes-rails)3
- [Learn To Code Resources](/series#learn-to-code-resources)3
- [Testing Anti-Patterns](/series#testing-anti-patterns)5
