---
title: Blocks, Procs, and Enumerable
teaser: A look under the hood at how blocks and procs are used in Ruby.
tags: ruby
author: Joël Quenneville
published_on: 2016-04-25
---

The [`Enumerable`] module is one of my favorite parts of Ruby. It allows us to
perform operations like `#each`, `#map`, `#inject`, and `#any?` on collection
objects, most notably `Array`. It's all much cleaner, readable, and semantic
than the nested `for` loops I used to write in other languages.

[`Enumerable`]: http://ruby-doc.org/core-2.2.3/Enumerable.html

`Enumerable` is made possible by leveraging one of Ruby's more powerful
constructs: blocks. They typically take the form of:

```ruby
collection.each { |item| puts item }
```

or

```ruby
collection.map do |item|
  item * 2
end
```

More cryptically, you may also see:

```ruby
collection.all?(&:valid?)
```

or

```ruby
collection.inject(:&)
```

Let's take a closer look at what's going on here.

## Blocks

Blocks allow methods to take arbitrary snippets of code as arguments and run
them. The pattern of passing in an [anonymous function] into a method is
commonly used across multiple languages. JavaScript, for example, is notorious
for its use of deeply nested anonymous callback functions.

```js
item.action(function(result) {
  result.otherAction(function(newResult) {
    console.log(newResult);
  });
});
```

In Ruby, you might express "multiply each element of this collection by 2 and
return the result" by passing the anonymous function `n * 2` to the
`Enumerable#map` method:

```ruby
[1, 2, 3].map { |n| n * 2 }
# => [2, 4, 6]
```

[anonymous function]: https://en.wikipedia.org/wiki/Anonymous_function

## Procs

The concept of passing functions as arguments to other functions is quite
powerful. Methods that have this ability are known as [higher order functions].
It is common (particularly in functional languages) to want to pass in a named
function instead of an anonymous one. Ruby allows us to do that with `Proc`s.

`Proc` is Ruby's function object. We can pass a proc object instead of a block
to any method by prefixing it with `&`. For example we could use the named
function `double` in our previous snippet:

```ruby
double = Proc.new { |n| n * 2 }

[1, 2, 3].map(&double)
# => [2, 4, 6]
```

[higher order functions]: https://en.wikipedia.org/wiki/Higher-order_function

## `#to_proc`

Ruby does this clever trick where it doesn't immediately try to run the `Proc`
passed into the function but instead calls `#to_proc` on it before execution.
This allows us to pass in _any object_ that responds to `#to_proc`.

```ruby
class Doubler
  def double(n)
    n * 2
  end

  def to_proc
    method(:double).to_proc
  end
end

doubler = Doubler.new

[1, 2, 3].map(&doubler)
# => [2, 4, 6]
```

## Symbols

Passing in an object that responds to `to_proc` might seem like a cool but
useless party trick that wouldn't be used in a production codebase. That's where
`Symbol` comes in. It defines `#to_proc` as a function that sends the message of
the same name as the symbol to the target object.

For example:

```ruby
[1,2,3].map(&:to_s)
# => ["1", "2", "3"]
```

sends the message `:to_s` to each item in the array.

To get a better idea of how this works, we can try to replicate this behavior on
`String`.

```ruby
class String
  def to_proc
    method_name = self # the string is the method name
    Proc.new { |item| item.send(method_name) }
  end
end

[1, 2, 3].map(&"to_s")
# => ["1", "2", "3"]
```

This allows us to write terser and more readable code. For example, "are all the
numbers even?" can be expressed as `numbers.all?(&:even?)` instead of
`numbers.all? { |n| n.even? }`.

## `Enumerable#inject`

`inject` (aka `reduce`) is one of the most powerful methods provided by
`Enumerable`. In fact, all of the other methods provided by `Enumerable` could
be written in terms of `inject` (This general concept is called *catamorphisms*.
This [paper] takes a more detailed look at the topic).  However, `inject` is
weird. It takes a block just like any other method in `Enumerable`. But there's
a twist. Taking a look at the docs:

> Combines all elements of enum by applying a binary operation, specified by a
> block **or a symbol** that names a method or operator.

This means that it can accept a symbol _instead_ of a block and that the symbol
will be used to send that message to the objects, just like `Symbol#to_proc`.

So you where you would use a traditional block syntax with `Symbol#to_proc`:

```ruby
[1, 2, 3].inject(&:+)
# => 6
```

you could just use the bare symbol

```ruby
[1, 2, 3].inject(:+)
# => 6
```

This can lead to the confusing expression:

```ruby
[true, false, true].inject(:&)
# => false
```

At first glance this may look like someone tried to use `Symbol#to_proc` but
forgot to fill in the method name. However, note that the `&` and `:` are
flipped. `Symbol#to_proc` uses `&:`, not `:&`.

What's actually happening is that `inject` is using the method `&` to combine
the elements: `true & false & true`. The equivalent using `Symbol#to_proc` would
be the even stranger looking

```ruby
[true, false, true].inject(&:&)
# => false
```

[paper]: http://www.cs.nott.ac.uk/~pszgmh/fold.pdf
