How can we implement Curry and Compose, with bind and reduce.

Javascript logo

We currently have several libs that support javascript’s mission to be functional as Lodash, Underscore and Ramda are one of them. So why I am talking about Pareto.js? Simple as the Pareto Principle, the lib created is meant to be light and to solve 80% of your problems with 20% code.

Usually I try to learn something demystifying the “magic” behind the implementation. That’s how I started to learn Angular, and now it is being applied to functional programming. So in this post we will evaluate the implementation of Curry and Compose in Pareto.js.

Curry

Curry is the action of taking a function that takes multiple arguments and turn it into a chain of functions, each of which receive only one parameter.

Let’s see the test on this function:

To begin to demystify the magic, we have two questions to ask:

How our will function store the parameters already passed?

What does Function.prototype.bind() has to do with it?

Function.prototype.bind()

We commonly use .bind() to pass to a function a context for its execution, but we forget something important, as stated in the documentation developer.mozilla.org:

Partial Functions The next simplest use of bind() is to make a function with pre-specified initial arguments. These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function…

Summing up:

One of the uses of .bind() is to build a function with pre specified initial arguments. These arguments will be passed after this value and will be inserted at the beginning of the arguments passed to the target function …

Hard to understand? Then we go to another example (in ES5 so you can open the devtools and test by yourself).

Note that the function myNumbers expects three parameters, every time we call .bind(this, val), the function returned by .bind() method automatically saves the passed argument.

And with that we come to the implementation of curry in Pareto.js, which will call curry.bind(this, fn, … args), stacking the parameters in the spread operator … args until the number of arguments is the same as the function wait (args.length === fn.length). If you have not understood what is … args, take a read in spread operator.

Compose

As its name suggests, Compose is to build more complex functions by simpler functions, composing them. Let the implementation in Pareto.js:

Let’s see the test of this function:

And so we have a question:

What is Array.prototype.reduce() is doing there?

Array.prototype.reduce()

Usually we think of.reduce() as an accumulator, but only in the meaning sum of values rather composition. We know that .reduce() applies a callback function on an accumulator, going trough all array elements. Let’s start the deconstruction of our compose:

We know that it takes an array of functions as arguments, through the spread operator …args;

The callback function to .reduce (), which will be executed on each item in our array, can receive up to four parameters, namely: previousValue, currentValue, index and array . But here we will only use the first two ( previousValue and currentValue ). Recalling that the first call to our callback function, previousValue will be the value of the first element of the array and currentValue will be the value of the following element ;

and . But here we will only use the first two ( and ). Recalling that the first call to our callback function, ; Our callback function will compose the function passed in previousValue with that at currentValue, adding the function declaration that it may receive N arguments (… args). Resulting in previousValue(currentValue(… args)).

According to our tests, let’s look at the steps of execution in a table:

Calls to the callback function of .reduce ()

And so we have the result of the inner function (moreExclaim) feeding the outer functions (exclaim and then toUpperCase).

And that it’s all folks. I hope this has helped you to understand the curry and compose relations with .bind() and .reduce(). Feedbacks are more than welcome and encouraged. Thanks for your time. :)

Sources:

https://en.wikipedia.org/wiki/Pareto_principle

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

https://github.com/concretesolutions/pareto.js

https://hughfdjackson.com/javascript/why-curry-helps/