Functional JavaScript: Currying Functions

Seth Barden
5 min readApr 6, 2018

--

When I first heard the term ‘function currying’ in JavaScript, I immediately thought, ‘Wow, a program that can drain three’s’.

But then I remembered that we are talking about functional programming and not functional jump shots.

In the simplest terms, function currying involves breaking up a function that takes several arguments into a high order function that returns functions that will receive the additional arguments to obtain a desired value in the future. Once all of the inner functions have been invoked, the final function will give us the desired outputted value.

Enough words. Let’s look at code!

Here, we have function animalDescription that takes in three arguments as strings: name, adjective, and animal. It then outputs a string concatenating those arguments. Let’s curry this function up!

curriedAnimalDescription is a higher order function that takes in a string of a name as an argument. It’s return value is a function that takes in a string of an adjective. That function’s return value is another function that takes in a string of an animal as an argument and returns a concatenated string of all of our arguments. Because functions are first class citizens in JavaScript and can be returned as values of other function, each return function inside curriedAnimalDescription is bound to the lexical environment in which they are declared. This is called a closure. Therefore the first function returned from invoking curriedAnimalDescription will always be bound to the value of name passed into curriedAnimalDescription. The same principle applies to all of our functions that will eventually be returned from curriedAnimalDescription. So by the time we will invoke our final enclose function, that function will be bound to arguments passed in for name and adjective once both of those enclosing functions are invoked. Before we go further, let’s invoke some of these functions, assign their return values to a const and check out their return values.

Above, we assign const riley to the return value of curriedAnimalDescription(‘Riley’) which is a function that is bound to the lexical environment in which name, as written in our in our original function declaration, is assigned to the string value ‘Riley’.

We then invoke riley with the argument 'good' and save the returned value to a variable called goodRiley. The value of goodRiley is a function that is now bound to the variable name pointing to the string 'Riley' and the variable animal pointing to the string 'good'.

Finally we invoke goodRiley with the string 'dog' as its argument and assign its return value to const rileyDescription. This value is a concatenated string that is still bound to our name and adjective values that were invoked in earlier functions. Therefore we are able to successfully return the string: “Riley is a good dog!”, which he is.

Why is this useful? Let’s take a look using another higher order function built on the Array prototype: filter.

Consider the following arrays of objects. These are a list of animals that are available for adoption and a list of people that are available to adopt them!

We can see that in each array, there are objects representing people and animals. A common key between the animal objects and people objects is availability. Let’s write a generic currying function that will give us some flexibility to filter each array based on the property availability of each object and its value, either true of false.

Our hasProperty function is flexible enough that we are able to declare little bits of it at a time. Let’s set a variable that will be bound to the property availability.

Now, let’s declare a const isAvailable that points to available(true). Its return value will be a function that takes an object as an argument and will return a boolean of true of false if the object’s available property is equal to the boolean true which in turn has already been bound to value from our hasProperty(‘available’) invocation.

Our isAvailable function can now be passed around as a callback to filter on both the animals and people arrays since both objects have keys of available that point to booleans.

As the filter method iterates through our object array, it passes each object to isAvailable. isAvailable is already bound to both the availability property and the value of true. So, the filter method uses isAvailable as a callback to construct a new array of both our animals and our people that are available for adoption and to adopt!

We have composed currying functions that are concise and can be reused later in our program. For example, if we had a list of dog house objects for sale with the key of availability pointing to a boolean telling whether the dog house was in stock or not, we could call filter on the dog house array and pass isAvailable yet again for a list of all dog houses that are available for purchase. We can reuse the tight and cleanisAvailable function if there are other animal objects in an array such as cats, goldfish and emus who are all fighting for adoption.

Our hasProperty function is generic enough that we can use it with any property and any value that we may come across while building our application. Reusable === good.

There are many other uses for currying functions. The examples are here are a basic way to understand the power of currying! Currying functions allows programs to manage variables, bind functions to specific contexts, and to delay executions of functions if an application is waiting for a response from another part of the application by binding values to functions that we do currently have.

Big shout out to Fun Fun Function and Kristina Brainwave for their awesome explanations!

--

--