Spread Partial Love

Using JavaScript's spread to enable partial application

Spread Partial Love

If you like functional programming, and maybe even if you don't, you may have come across the concepts currying and partial application.

A multi-argument function is "curried" when its evaluation is translated into a sequence of one argument functions. For example, a three argument adder function

const adder = (x, y, z) => x + y + z;

is turned into a sequence of three functions

const adder = (x) => (y) => (z) => x + y + z;

We can use curried functions to make new functions via partial application.
adder could become add10 by calling adder with an x argument of 10.

const add10 = adder(10);
// add10 = (y) => (z) => 10 + y + z

The same logic applies when we apply another argument to add10

const add10and100 = add10(100);
// add10and100 = (z) => 10 + 100 + z

Languages like F#, Haskell, OCaml, etc. curry our functions automatically. Others like Scala have features that make it easier to do it ourselves.
Unfortunately, these aren't languages the average developer gets to use in the office. Even those who do might still be stuck using JavaScript on the front-end.

To reap the benefits of currying in JavaScript, our only option is to write functions in the explicitly curried style. In personal projects, it's fine.
Writing explicitly curried functions at work, however, is a completely different story. Living in an object-oriented world, even if coworkers are ok with writing curried functions, the chances of them doing the same are slim.

Since a handful of explicitly curried functions isn't very useful, we need a different approach. Enter the spread!

The spread syntax, represented by ..., is one of the more recent additions to JavaScript.

spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected. - MDN

The spread syntax is going to help us write a function called partial. partial will use a closure to wrap a function with some or all of its arguments, mimicking partial application. When we call the new partially applied function, we'll spread the original arguments - with any additional arguments supplied at the call - into the wrapped function to obtain the result.
We'll can use partial to partially apply arguments to regular functions like adder.

const partial = (fn, ...args1) => (...args2) => fn(...args1, ...args2);

partial takes a function fn, and a variable number of arguments courtesy of the spread. It returns a function that also takes a variable number arguments and returns the result of calling fn with both groups of arguments.

We'll use the same adder function we used above to demonstrate partial.

const adder = (x, y, z) => x + y + z;

We can use partial to partially apply multiple arguments at once:

const add300 = partial(adder, 100, 200);

const result = add300(1000); // 1300

Or we can also apply the majority of the arguments when we're ready for the result:

const add100 = partial(adder, 100);

const result = add100(500, 1000); // 1600

We can even mimic our explicitly curried function by passing partials to partials:

const add100 = partial(adder, 100);
const add300 = partial(add100, 200);

const result = add300(300); // 600

Now we can reap the benefits of partial application without having to worry about whether the entire team (or the standard library) is writing explicitly curried functions.

Love the spread and spread the love.

Reference: Currying, Partial Application, Curry or Partial Application by Eric Elliott, Clojure's partial,