By Rick Henry

Making use of this functional technique can make your code more elegant

Image

Functional programming gives us techniques to solve problems in our code. One of these, partial application, is a little tricky to understand but it can allow us to write less of it (sounds interesting, right?).

What is it?

Partial application starts with a function. We take this function and create a new one with one or more of its arguments already “set” or partially applied. This sounds odd, but it will reduce the number of parameters needed for our functions.

Let’s give some context around when we could use partial application:

const list = (lastJoin, ...items) => {  const commaSeparated = items.slice(0,-1).join(", ");  const lastItem = items.pop();  return `${commaSeparated} ${lastJoin} ${lastItem}`;}

This little function takes in a single word, lastJoin, and an arbitrary number of items. Initially, list declares a commaSeparated variable. This variable stores a comma separated joined array of all the elements except the last. On the next line we store the last item in items in a lastItem variable. The function then returns using a string template.

The function then returns the items, as a string, in list format. For example:

list("and", "red", "green", "blue");     // "red, green and blue"list("with", "red", "green", "blue");    // "red, green with blue"list("or", "red", "green", "blue");      // "red, green or blue"

Our list function allows us to create lists when we want. Each type of list we create, “and”, “with”, “or” is a specialisation of the general list function. Wouldn’t it be nice if they could be functions of their own?!

How to use partial application

This is where partial application can help. For example, to make a listAnd function, we “set” (or partially apply) the lastJoin argument to be “and”. The result of doing this means we can invoke our partially applied function like this:

listAnd("red", "green", "blue");    // "red, green and blue"

It doesn’t need to stop there either. We can make many specialised functions by partially applying an argument to our list function:

listOr("red", "green", "blue");      // "red, green or blue"listWith("red", "green", "blue");    // "red, green with blue"

To do this, we need to create a partial utility function:

const partial = (fn, firstArg) => {  return (...lastArgs) => {    return fn(firstArg, ...lastArgs);  }}

This function takes a function fn as it’s first parameter and firstArg as its second. It returns a brand new function with one parameter, lastArgs. This gathers up the passed in arguments.

Now to make our listAnd function we invoke partial passing in our list function and our last join word:

const listAnd = partial(list, "and");

Our listAnd function now only takes an arbitrary list of items. This function when invoked will, in turn, invoke the passed in list function. We can see that it will be passed “and” as the first argument and the gathered lastArgs thereafter.

We’ve now created a partially applied function. We can use this specialised function over and over again in our program:

listAnd("red", "green", "blue");    // "red, green and blue"

Taking it further

The partial function we created is to illustrate how partial application works. There are some great functional JavaScript libraries available which have this utility built in, such as Ramda JS.

It’s worth noting that even if you are new to partial application as a concept there is every chance you have been using it. If you have ever used the .bind() method on a function this is an example of partial application. It’s common practice to pass this into bind to set its context. Under the hood it’s partially applying this and returning a new function.