Real world example of compose function and currying.
Tags: functional, currying, composition, javascript
Published: 2021-04-22 18:00:09


## Another currying article
Using Javascript, you can decide to write your code based on FP or OOP principles. When you decide on FP there are some concepts you need to understand in order to make the most out of FP principles. These include concepts like currying and compose functions. For me it took a while to understand what the **currying** is and **when** and **how** I should use it in my code. Here, I tried to explain what I found in a simple way, hopping to make the learning process quicker and smoother for you.

- [When to use compose functions?](#when)
- [How to use compose functions?](#how)
- [How to enhance compose functions using currying?](#how-2)
- [Homework](#homework)
- [Your opinion](#opinion)

## <a name="when"></a>When should we use compose functions in our code?
we want to model the following ice cream production line by using javascript functions.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6pb168ls15vhgxrv1rn3.jpg)

We see a sequence of 3 actions following one another: 
- **Mix** the ice cream with sth like 🍓, 🍒 and 🍇.
- **Decorate** the ice cream with sth like 🍫.
- **Form** the ice cream scoopes.

All actions take ice cream as input, modify it with some settings(berries or chocolate) and send the modifed ice cream to the ouput to be used by next function.

Here is the atomic function for each action. 
```javascript
function mix(ice, tastes) {
	return tastes.join(', ') + ice;
}

function decorate(ice, taste) {
	return 'decorated with ' + taste;
}

function form(ice) {
	return 'scooped ' + ice;
}
```
 For a berry ice cream with chocolate topping, you might write:
 ```javascript
 decorate(form(mix(ice, 🍓, 🍒, 🍇)), 🍫)
 // output: " scooped 🍓, 🍒, 🍇 ice cream decorated with 🍫"
 ```

I'm sure you've seen this pattern in your code: 
Modifying a single data (ice cream) by a couple of operations to create the desired outcome (scooped berry ice cream with chocolate). 
But this way of writing function sequences is not quite nice. The brackets are too many, and the execution order is from right to left.
To write it better, we can use the **Composition Function** concept in math:

> Having 
> - f: x -> y
> - g: y -> z
> 
> we can create a third function which receives a single input(x) and creates an output(z)
> - h: x -> z
> 
> it looks like 
> - h(x) = g(f(x))

## <a name="how"></a>3 steps to write a better function sequence using the composition function in JS

**1. Create a new compose function**
For me the simplest compose function would be a wrapper function, which receives all required inputs and returns the results of the function sequence execution. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2otthyirnkegrgafhs9e.jpg)
```javascript
const compose = (ice, tastes, decorateTaste) => 
	form(decorate(mix(ice, tastes), decorateTaste));

// call compose
compose('ice',['🍓', '🍒', '🍇'], '🍫');

// output: " scooped 🍓, 🍒, 🍇 ice cream decorated with 🍫"
```

**2. Reduce the compose function's input parameters**
Compose function should take only one single input. This is the data that gets modified throught the function sequence and comes out as output. In our example ice cream is this data.
It matters to keep compose function unary because when calling compose function we only want to focus on the data that is sent to the method and not care about the setting parameters.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6n8qbpddt03urr3jjre4.jpg)
As you see in the above picture, Each action(mix, decorate) can be customized by its corresponding setting parameters(berries and chocolate): 
 ```javascript
// Customized version of mix function using berries
const mixWithBerries = ice => mix('ice', ['🍓', '🍒', '🍇']);

// Customized version of decorate function using chocolate
const decorateWithChoclate = ice => decorate('ice', '🍫');

// Compose function accepts just one single input
const compose = (ice) => form(decorateWithChoclate (mixWithBerries(ice)));

// Call compose. looks nicer!
compose('ice');
 ```

**3. A more elegant generic way of creating compose functions**
In this section we write a compose function **generator**. Why? Because it is more convenient to use a compose function generator rather than to write a compose function every time if you use compose functions a lot.

> You can skip this section if you want to use composeGenerator function available in lodash/fp and ramda libraries.

We also implement our compose function generator in a more elegant fashion than our previous implementation of compose function, where we still have a lot of brackets and the execution order is still from right to left.

Then compose function generator is a function that takes a series of functions(fn1, fn2, ..., fnN) as input parameters and returns a new function(compose).  The returned compose function receives data and executes functions(fn1, fn2, ..., fnN) in a given order.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0kpy0pmqluo8an4c3af.jpg)
That looks like this:
```javascript
const composeGenerator = (fn1, fn2, fn3) => data => fn1(fn2(fn3(data)))

// create compose function using composGenerator
const compose = composeGenerator(form, decorate, mix)
compose('ice')

// or
composeGenerator(form, decorate, mix)('ice')
```
The double arrow in the code above indicates a function `composegenerator(fn1, fn2, fn3)` which returns another function `compose(data)`. 

This implementation of composeGenerator is limited to 3 functions. We need something more generic to compose as many functions as you want:

 ```javascript
const composeGenerator = (...fns) => data => 
	fns.reduceRight((y,  fn) => fn(y), data)

const compose = composeGenerator(form, decorateWithBerries , mixWithChoclate )
compose('ice')

// or
composeGenerator(form, decorateWithBerries , mixWithChoclate )('ice')
```
It's not easy but at least you define it once, and then you don't have to worry about the complexity anymore. Let's break it down into a group of smaller parts to make it easier to understand.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/znabbmv0vk55l58y6pph.jpg)
And here is how reduceRigth works when we call composeGenerator with our piepeline functions.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7cwuo3mxsxc6oh5urbmq.jpg)

## <a name="how-2"></a>Enhance your compose function with currying
Our solution to remove the setting parameter from our compose function is not good since we will have to write new custom function every time we wish to add a new flavor to our pipeline:
```javascript
// Change the production line to decorate with 🍓
const decorateWithStrawberry = ice => decorate('ice', ['🍓']);
composeGenerator(form, decorateWithStrawberry , mixWithChoclate )('ice');

// Change the production line to decorate with 🍓 and 🍫
const decorateWithChocAndStrawberry = ice => decorate('ice', ['🍓', '🍫'])
composeGenerator(form, decorateWithChocAndStrawberry , mixWithChoclate )('ice')
```
Our solution is to implement the **curry** function, which accepts the tastes and returns the decorate function with one single argument.
``` javascript
// Currying decorate function
const curriedDecorate = (tastes) => (ice) => decorate(ice, tastes);
// Currying mix function
const curriedMix = (taste) => (ice) => decorate(ice, taste);

composeGenerator(
	form, 
	curriedDecorate('🍫') , 
	curriedMix(['🍓', '🍒', '🍇]))('ice')
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8iny4c9a7pbyo19ih8f.jpg)

Like compose functions, we may write our curried functions ourselves or create a generic function that returns a curried version of a function.


> You can skip this section if you want to use curry function available in lodash/fp and ramda libraries.

A curry function receives a function `fn` as input. If the passed arguments(`args.length`) are at least equal to the function `fn`'s required arguments(`fn.length`), it will execute function `fn`, otherwise it will return a partially bind callback.
```javascript
const curry = fn => ()  ({
		const args = Array.prototype.slice.call(arguments)
		return args.length >= fn.length ? 
			fn.apply(null, args) : 
			currify.bind(null, ...args) 
	})

curry(decorate)(['🍓','🍫']) //output: a function which just needs ice cream as input
```

When we execute a curryFunction(curriedDecorate) with all the setting parameters(decorateTaste), it returns a new function which only needs one data parameter, and we can use it in our compose function.


## <a name="homework"></a>A homework for you:
Generally, remember that currying is used to decrease the number of parameters of a function. In our last example, we saw that reducing inputs to a single one can be beneficial when using a compose function but unary functions can be used in more cases where we only require a single argument. For example in arrow functions we can remove the brackets when function just has one parameter:
```javascript
// 👎
[1,2,3].map(function(digit) {
	return digit * 2
})

// 👍
[1,2,3].map(digit => digit * 2)
```

As a pratice try to improve this code using currying. 
```javascript
const pow = (base, exponent) => Math.pow(base, exponent)
const digits = [1,2,3];
const exponent = 2;
digits.map(digit, function(digit) {
	return pow(digit, exponent)
})
```
you can find the solution in this [video](https://www.youtube.com/watch?v=fvJ9yWqXcZI) from Derick Bailey

## <a name="opinion"></a>Your opinion
What is your favorite example of using currying in your code? And generally do you like using it or do you think it makes the code unnecessarily complicated ?