# JavaScript Currying: Its really just reduce over variadic input. …and its not that hard.

--

Currying is a technique of converting a function that takes n-number parameters to an n-chain of functions that takes one parameter at a time until all n-number parameters are collected and the function is evaluated. Consider the functions `sum2`

and `sum3`

:

`const sum2 = (a,b) => a + b`

const sum3 = (a,b,c) => a + b + c

We could define them in curried form by writing them like this:

`const sum2 = a => b => a + b`

const sum3 = a => b => c => a + b + c

A practical reason to favor curried form occurs in certain situations where you want automatic partial applications. Consider the two increment functions. The first `incrA`

where it is built off of curried form`sum2`

function and the second where `incrB`

it is built off of a traditional (also called tupled form) `sum2`

:

// if sum2 is in curried form

const incrA = sum2(1)// if sum2 is in tupled form

const incrB = (b) => sum2(1, b)

The latter requires some boilerplate while the former reads a little bit clearer. Writing a function that takes a 2-tuple or 3-tuple input in a curried form is relatively trivial. However as the number or parameters increase writing in curried form can be a bit gnarly. We can solve this by creating a magic function that does this for us.

Consider a very specific function `curry2`

that takes a 2-tuple and converts it to its curried form:

`const curry2 = f => a => b => f(a, b)`

`curry2`

takes as input a function `f`

(e.g. sum2) and then each individual argument `a`

& `b`

and when it has both of them invokes the captured function `f `

with those parameters.

`const sum2Tupled = (a,b) => a + b`

const sum2Curried = curry2(sum2Tupled)

While we can work on a number of utility functions curry2, curry3, curry4 etc. However there is a slightly better way — we can leverage

- variadic input
- spread operator
- reduce
- and papply

Lets take this backwards. `papply`

is a utility function that takes a function and an input and partially applies that input to that function. The effect is similar to that of a function defined in a curried form, but lacking somewhat in syntactic sugar.

`// consider sum2 defined in tupled form`

const incr = papply(sum2, 1)

This utility (**papply**) is fairly easy to write:

`const papply = (f, x) => f.bind(null, x)`

The next step is defining `reduce`

. As we know (article on reduce) that `reduce`

has the intent of aggregating a list into a single value through a self-provided reducing function:

**const ***head *= xs => xs[0]

**const ***tail *= xs => xs.slice(1)

**const ***reduce *= (f, agg, list) =>

(list.length** **== 0) ?

agg :

*reduce*(f, f(agg, *head*(list)), *tail*(list)) ;

To define the magical `curry`

function we need to combine the papply with reduce and the magical spread operator:

**const ***curry *= f =>

(f.**length **== 0) ?

f() :

(...xs) => *curry*(reduce(*papply*, f, xs)) ;

`curry`

takes a function `f`

. If that functions has had all of its arguments bound, it is invoked and the result are returned. If that function (`f`

) still has free arguments `curry`

then returns an anonymous function that takes any number of inputs, captured as an array via spread operator `…xs`

. Those inputs are then partially applied onto `f`

via `papply`

by `reduce`

. We then `curry`

that result which starts the entire process over (i.e. check to see if all of the arguments are bound).

To remind ourselves of how reduce works to sum lists:

const add2 = (a,b) => a + b// using a list processing library

const sumList = list => reduce(add2, 0, list)

reduce takes something that combines two objects — in the case of `sumList`

this is `add2`

. The combiner takes these objects in a particular order. The first object is the running aggregate. The second object is the next thing to be applied to that aggregate. `Reduce`

also takes an initial value — in the case of `sumList`

this is `0`

. Lastly it takes the list `list`

.

Applying this thought process to `curry:`

`reduce(`*papply*, f, xs)

The inital value is the captured function `f`

; In this case it has free parameters. The combining function here is `papply`

which creates a new function by taking a function (the running aggregate) and any one parameter and partially applying it. `reduce`

repeats this process for every item in the list `xs`

.

We can then apply this version of curry to any tupled/traditionally defined function. But please leverage a version from either Ramda or Sanctuary. My implementation doesn’t handle:

- the attempt to curry a function that doesn’t take input
- the application of more parameters than the captured function intends to take