This post is Part 2 of a series about functional programming called Thinking in Ramda.

In Part 1, I introduced Ramda and some of the basic ideas about functional programming, such as functions, pure functions, and immutability. I then suggested that a good place to start is with the collection-iteration functions such as `forEach`, `map`, `select`, and friends.

## Simple Combinations

Once you’ve gotten used to the idea of passing functions to other functions, you might start to find situations where you want to combine several functions together.

Ramda provides several functions for doing simple combinations. Let’s look at a few.

### Complement

In the last post, we used `find` to find the first even number in a list:

What if we wanted to find the first odd number instead. We could always write an `isOdd` function and use it, but we know that any number that isn’t even is odd. Let’s reuse our `isEven` function.

Ramda provides a higher-order function, `complement`, that takes another function and returns a new function that returns `true` when the original function returns a falsy value, and `false` when the original function returns a truthy value.

Even better is to give the `complement`ed function its own name so it can be reused:

Note that `complement` implements the same idea for functions as the `!` (not) operator does for values.

### Both/Either

Let’s say we’re working on a voting system. Given a person, we’d like to be able to determine if that person is eligible to vote. Based on our current knowledge, a person must be at least 18 years old and be a citizen in order to be able to vote. Someone is a citizen if they were born in the country or if they later became a citizen through naturalization.

What we’ve written above works, but Ramda provides a couple of handy functions to help us clean it up a bit.

`both` takes two other functions and returns a new function that returns `true` if both functions return a truthy value when applied to the arguments and `false` otherwise.

`either` takes two other functions and returns a new function that returns `true` if either function returns a truthy value when applied to the arguments and `false` otherwise.

Using these two functions, we can simplify `isCitizen` and `isEligibleToVote`:

Note that `both` implements the same idea for functions as the `&&` (and) operator does for values, and `either` implements that same idea for functions as the `||` (or) operator does for values.

Ramda also provides `allPass` and `anyPass` that take an array of any number of functions. As their names suggest, `allPass` works like `both`, and `anyPass` works like `either`.

## Pipelines

Sometimes we want to apply several functions to some data in a pipeline fashion. For example, we might want to take two numbers, multiply them together, add one, and square the result. We could write it like this:

Notice how each operation is applied to the result of the previous one.

### pipe

Ramda provides the `pipe` function, which takes a list of one or more functions and returns a new function.

The new function takes the same number of arguments as the first function it is given. It then “pipes” those arguments through each function in the list. It applies the first function to the arguments, passes its result to the second function and so on. The result of the last function is the result of the `pipe` call.

Note that all of the functions after the first must only take a single argument.

Knowing this, we can use `pipe` to simplify our `operate` function:

When we call `operate(3, 4)`, `pipe` passes the `3` and `4` to the `multiply` function, resulting in `12`. It passes that `12` to `addOne`, which returns `13`. It then passes that `13` to `square`, which returns `169`, and that becomes the final result of `operate`.

### compose

Another way we could have written our original `operate` function is to inline all of the temporary variables:

That’s much more compact, but somewhat harder to read. In that form, however, it lends itself to be rewritten using Ramda’s `compose` function.

`compose` works exactly the same way as `pipe`, except that it applies the functions in right-to-left order instead of left-to-right. Let’s write `operate` with `compose`:

This is exactly the same as `pipe` above, but with the functions in the opposite order. In fact, Ramda’s `compose` function is written in terms of `pipe`.

I always think of `compose` this way: `compose(f, g)(value)` is equivalent to `f(g(value))`.

As with `pipe`, note that all of the functions except the last must only take a single argument.

### compose or pipe?

I think that `pipe` is probably the easiest to understand when coming from a more imperative background since you read the functions left-to-right. But `compose` is a bit easier to translate to nested-function form as I showed above.

I haven’t yet developed a good rule for when I prefer `compose` and when I prefer `pipe`. Since they are essentially equivalent in Ramda, it probably doesn’t matter which one you choose. Just go with whichever one reads the best in your situation.

## Conclusion

By combining several functions in specific ways, we can start to write more powerful functions.

## Next

You may have noticed that we mostly ignored the function arguments when we were combining functions. We only supply the arguments when we finally call the combined function.

This is common in functional programming, and we talk about that a lot more in the next post in this series, Partial Application. We also talk about how to combine functions that take more than one argument.