One of the lesser understood functions in Enumerable for many Rubyists is reduce . It’s just the thing we can use to get sums right? Well, sum does that in Ruby 2.4.x and above. Does that make it useless now?

The secret of reduce is that every other Enumerable function can be implemented in terms of reduce. Yes, every last one of them.

Before we get into that though, let’s take a look at a few other higher order functions in Ruby and what they do.

Map

Let’s start off with map . Map is used to apply a function to an Enumerable collection. In more common terms, every item goes through the function individually and you get a new Array at the end:

[1,2,3].map { |i| i * 2 }

# => [2,4,6]

Now an important thing to keep in mind is that map does not mutate the original array, it returns a new one.

Select

Select is like map, except it uses the function as a predicate. If it happens to be true, we keep the element for the new list, otherwise get rid of it:

[1,2,3].select { |i| i > 1 }

# => [2, 3]

Reduce

So before we get too far into it, we need to cover the base case for reduce . What does it do and how does it do it? We’ll start with a basic sum:

[1,2,3].reduce(0) { |accumulator, i| accumulator + i }

# => 6

For a first time reader, that’s dense. Let’s break it down:

[1,2,3].reduce(0)

We’re reducing our list with an initial value of 0 .

{ |accumulator, i| accumulator + i }

and we’re passing it a block which takes an accumulator , and i . The first value of the accumulator is either our initial value ( 0 ) or the first element of our list.

For every cycle of reduce, accumulator is set to the return value of the last cycle. For our current list, that might look like this:

a | i | reducer

---+---+-----------

0 | 1 | 0 + 1 : 1

1 | 2 | 1 + 2 : 3

3 | 3 | 3 + 3 : 6

6 | - | -

---+---+----------- Returns: 6

As soon as it gets to the end of the list, it gives us back our accumulator. A name that may help understand what reduce is doing is a name it has in other languages: foldLeft . Basically we’re folding our list to the left with a + , giving us something that looks like this:

((((0) + 1) + 2) + 3)

Now we can get rid of the parens, but for the sake of delineation of the new value of accumulator we’ll leave them there for now.

For amusements sakes though, one could certainly compare this to LISP as well: