# The Array.reduce Method Part 5 - Making a Compose Operation

Greetings, friends! This is Part 5 of my tutorial series on the Array.reduce method in JavaScript! In this tutorial, I will discuss how to create your very own `compose`

function. A `compose`

function is very similar to the `pipe`

function we discussed in Part 3, but you specifiy operations in reverse.

## Function Composition

In Part 3, I briefly discussed function composition. In this tutorial, I'd like to revisit that topic and discuss function composition in more detail.

Function composition is commonly used in mathematics.

```
f(x) = function of some value, x
g(x) = a different function of some value, x
h(x) = g(f(x)) = function "g" composed with function "f"
```

In JavaScript, we can use function composition to create a new function:

```
function f(x) {
return x * 2;
}
function g(x) {
return x * 3;
}
function h(x) {
return g(f(x));
}
// h(5) = (5 * 2) * 3
console.log(h(5)); // 30
```

Using arrow functions, we can make the code significantly shorter:

```
const f = x => x * 2;
const g = x => x * 3;
const h = x => g(f(x));
// h(5) = (5 * 2) * 3
console.log(h(5)); // 30
```

This implementation of function composition works, but it could be cleaner. Imagine if we had to perform a lot of function compositions. Our code would start becoming harder to read.

```
const array = [-1, 1, -2, 2, -3, 3, -4, 4];
const mapDouble = array => array.map(x => x * 2);
const mapTriple = array => array.map(x => x * 3);
const filterEven = array => array.filter(x => x % 2 === 0);
const filterPositive = array => array.filter(x => x > 0);
const result = mapTriple(filterEven(filterPositive(mapDouble(array))));
console.log(result); // [6, 12, 18, 24]
```

It would be nicer if we had a `compose`

function that would accept a list of functions as arguments.

## Compose Operation Using Array.reduceRight

In Part 4, we learned that the Array.reduceRight method exists. We can use it to create a `compose`

function:

```
const compose = (...functions) => initialValue => functions.reduceRight(
(acc, fn) => fn(acc),
initialValue
)
```

You may notice that this is very similar to the `pipe`

function we created in Part 3.

```
const pipe = (...functions) => initialValue => functions.reduce(
(acc, fn) => fn(acc),
initialValue
)
```

Yep! That's right. The `compose`

function is implemented the same way as the `pipe`

function, but it uses the `reduceRight`

method instead to iterate through an array in reverse.

Let's use our shiny new `compose`

function in an example.

```
const compose = (...functions) => initialValue => functions.reduceRight(
(acc, fn) => fn(acc),
initialValue
)
const array = [-1, 1, -2, 2, -3, 3, -4, 4];
const mapDouble = array => array.map(x => x * 2);
const mapTriple = array => array.map(x => x * 3);
const filterEven = array => array.filter(x => x % 2 === 0);
const filterPositive = array => array.filter(x => x > 0);
// Similar to: mapTriple(filterEven(filterPositive(mapDouble(array))))
const compositeFunction = compose(
mapTriple,
filterEven,
filterPositive,
mapDouble
);
const result = compositeFunction(array);
console.log(result); // [6, 12, 18, 24]
```

Our code looks much nicer now! Notice that the `compose`

function will return a new function. If we wanted to run the new "composed" function directly on a value, we could rewrite the code to the following:

```
// Same as: mapTriple(filterEven(filterPositive(mapDouble(array))))
const result = compose(
mapTriple,
filterEven,
filterPositive,
mapDouble
)(array);
console.log(result); // [6, 12, 18, 24]
```

The following table shows what happens during each iteration of the `reduceRight`

method inside the `compose`

function.

iteration | accumulator | current value | return value |
---|---|---|---|

1st | -1, 1, -2, 2, -3, 3, -4, 4 | mapDouble | -2, 2, -4, 4, -6, 6, -8, 8 |

2nd | -2, 2, -4, 4, -6, 6, -8, 8 | filterPositive | 2, 4, 6, 8 |

3rd | 2, 4, 6, 8 | filterEven | 2, 4, 6, 8 |

4th | 2, 4, 6, 8 | mapTriple | 6, 12, 18, 24 |

## Compose vs Pipe

The main difference between `compose`

and `pipe`

is that the operations supplied to the function argument of `pipe`

should be in reverse to achieve the same result as `compose`

.

Let's look at an example.

```
const compose = (...functions) => initialValue => functions.reduceRight(
(acc, fn) => fn(acc),
initialValue
)
const pipe = (...functions) => initialValue => functions.reduce(
(acc, fn) => fn(acc),
initialValue
)
const array = [-1, 1, -2, 2, -3, 3, -4, 4];
const mapDouble = array => array.map(x => x * 2);
const filterEven = array => array.filter(x => x % 2 === 0);
const composedResult = compose(mapDouble, filterEven)(array);
const pipedResult = pipe(filterEven, mapDouble)(array);
console.log('Composed result: ', composedResult); // [-4, 4, -8, 8]
console.log('Piped result: ', pipedResult); // [-4, 4, -8, 8]
```

The following table shows what happens during each iteration of the reducer inside both the `compose`

and `pipe`

functions in the above example.

iteration | accumulator | current value | return value |
---|---|---|---|

1st | -1, 1, -2, 2, -3, 3, -4, 4 | filterEven | -2, 2, -4, 4 |

2nd | -2, 2, -4, 4 | mapDouble | -4, 4, -8, 8 |

The order of operation definitely matters. Let's see what happens if we passed operations to the `pipe`

function in the same order as the `compose`

function.

```
const compose = (...functions) => initialValue => functions.reduceRight(
(acc, fn) => fn(acc),
initialValue
)
const pipe = (...functions) => initialValue => functions.reduce(
(acc, fn) => fn(acc),
initialValue
)
const array = [-1, 1, -2, 2, -3, 3, -4, 4];
const mapDouble = array => array.map(x => x * 2);
const filterEven = array => array.filter(x => x % 2 === 0);
const composedResult = compose(mapDouble, filterEven)(array);
const pipedResult = pipe(mapDouble, filterEven)(array);
console.log('Composed result: ', composedResult); // [-4, 4, -8, 8]
console.log('Piped result: ', pipedResult); // [-2, 2, -4, 4, -6, 6, -8, 8]
```

Totally different result! This is why the `pipe`

function should pass in operations in the reverse order of the `compose`

function if you want the return values to be the same. This makes sense because the `compose`

function uses the `reduceRight`

method in its implementation, and the `pipe`

function uses the `reduce`

method instead.

## Conclusion

We have now seen an advanced use case of the `reduceRight`

method in JavaScript. We can use this method to create a `compose`

function that performs function composition on a list of functions or operations. The `compose`

function will be very useful when we talk about transducers in the next lesson.