A Complete Guide to JavaScript Currying: What Does it Mean?

Functional programming in Javascript allows you to pass a function as an argument and return a function. This programming style introduces you to several concepts you would also encounter in other programming languages like Python, Erlang, Scala, and many more. They include:

  • Function currying
  • Pure and Impure functions
  • High order functions

We already did a blog on “Pure and Impure Functions in JavaScript.” This post will focus on currying in Javascript.

Currying is when a function doesn’t take all its arguments upfront. Instead, you pass the first argument, and the function returns another function that you are supposed to call with the second argument. That will, in turn, return a new function which you will call with the third argument. That goes on and on until you provide all the arguments. The function at the end of the chain will return the value you need.

As you might have already seen, currying is an advanced technique for working with Javascript functions – a concept borrowed from lambda calculus. However, that shouldn’t scare you, as the implementation is much easier than you imagine. This post will also give you a small “Partial Application” walkthrough to ensure you don’t confuse it with currying.

What is Currying?

First things first—The term “curry” in programming is not related to “curry,” the food spice. It’s a technique of transforming functions in Mathematics and Computer Science named after the great American mathematician and logician Haskell Brooks Curry.

As described above, currying transforms a function that takes multiple arguments into a series of nesting functions that return functions that take the subsequent arguments inline. The last function will do the final computation and return the necessary value.

That might sound a little confusing when said in theory. The code snippet below will give you a better understanding.

//UNCURRIED FUNCTION
//Takes 3 arguments and returns the sum of all

function addNums (a,b,c){
  return a + b + c;
}
console.log(addNums(2,3,4));

//Returns: 9

The code snippet above shows a simple function that calculates the sum of three numbers passed as arguments. Let’s transform it into a curried function.

//CURRIED FUNCTION

function addNums(a){
  return function (b){
    return function(c){
      return a + b + c
    }
  }
}

console.log(addNums(3)(4)(7))
//Returns: 14

In the code snippet above, the function addNums() takes a single argument a and returns the second function, which takes the argument b , which in turn returns a third function which in turn takes arguments c. The third function computes the sum of the three numbers and returns a value.

Tip: In programming, arity is a term used to refer to the arguments passed in a function. For example, fnOne(a,b) is a 2-arity function as it takes two arguments. fnTwo(x,y,z) is a 3-arity function as it takes three arguments.

Below are several practicals to help you have a solid understanding of currying in Javascript.

Currying in JavaScript: Example 1

Take a look at the function below.

function sportBike(owner,year,model){
  return owner +" rides a " + year + " " + model;
}
console.log(sportBike("John",2015,"Kawasaki"));

/*Output:
John rides a 2015 Kawasaki

In the code above, the sportBike() function takes three arguments: owner, year, and model. The function uses string concatenation to form a readable sentence, as seen in the output section. You can use currying to transform this function, as shown below.

function sportBike(owner) {
  return function (year) {
    return function (model) {
      return owner + " rides a " + year + " " + model;
    };
  };
}

In the code above, the sportBike() function takes one argument – owner and returns a function. The returned function, in turn, takes one argument – year and also returns another function. The returned function also takes one more argument – model and returns the expected value.

To call the sportBike() function after currying, you will write it as follows:

sportBike("John")(2015)("Kawasaki");
/*Output:
John rides a 2015 Kawasaki

Notice that you are not passing all three arguments in one function this time. Instead, you are using the syntax sportBike()()() , which allows you to pass the argument for every function in order. Please note that these arguments are the ones that invoke the functions.

Therefore, if you used the syntax sportBike()(), the last function that returns the final value (string) will not execute.

To keep things clean and neat, you can also use arrow functions to have a more readable code. See the snippet below.

const sportBike = (owner) => (year) => (model) => 
      owner + " rides a " + year + " " + model;
  
sportBike("John")(2015)("Kawasaki");

/*Output:
John rides a 2015 Kawasaki

There are situations where you might need to reuse the same value. Instead of invoking a function with the same variable multiple times, you can decide to break the functions as shown below.

function sportBike(owner) {
  return function (year) {
    return function (model) {
      return owner + " rides a " + year + " " + model;
    };
  };
}

let yearOfManufacture = sportBike("John") //Returns the second functon which expects the argument - year
let bikeName = yearOfManufacture(2019) //Returns the third (last) functon which expects the argument - model

console.log(bikeName("Kawasaki"))
/*Output:
John rides a 2019 Kawasaki

So what is happening here? You will notice that there are two new functions in our program – yearOfManufacture() and bikeName(). Yes! Those two are indeed functions.

The yearOfManufacture represents the second function in the program. That’s because it invokes the first function sportBike() and passes the first argument – owner. This function will, in turn, return the second function that requires the second argument – year. Therefore, to pass the year argument (second argument), you will need to invoke the yearOfManufacture function.

bikeName() represents the third function in the program. It invokes the yearOfManufacture() function that returns a function (third function) that takes the model argument. That is also the last function in the program and returns the last value – a string.

Currying in JavaScript: Example 2

Alternatively, you can write your functions the standard way (without currying), then use a library like Lodash to transform them into a curryable function. Take a look at the code snippet below.

function addNums(a, b, c) {
  return console.log(a + b + c);
}
addNums(3,4,5)

/*Output:
12

The code above shows a function, addNums(), that takes three arguments and returns the sum. It is a simple standard function without any currying functionalities. To transform addNums() to a curryable function, you would write it as follows.

let log = console.log;

function addNums(a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
}
log(addNums(3)(4)(5))

/*Output:
12

Pretty easy, right? If you wish to write less code, you can use a library like Lodash, which automatically transforms your standard function into a curryable one. To start, install the Lodash library using the command below if you are in a NodeJS environment.

npm install lodash

After a successful install, use Lodash to transform the addNums() function into a currayble function. See the code below.

import _ from "lodash"
let log = console.log;

function addNums(a, b, c) {
  return console.log(a + b + c);
}
addNums = _.curry(addNums)
log(addNums(12)(13)(14));

/*Output:
39

In the first line, import _ from "lodash" imports the whole Lodash library to your program. To transform any function into a currayble function using Lodash, use the curry() method as shown in the line addNums = _.curry(addNums).

Quite interesting, right? With one line, you have converted a whole function to a curryable function. The code looks cleaner and is easy to read and debug.

Currying in JavaScript: Example 3

This section will show you a real-life scenario where you can implement Javascript currying using a library like Lodash. Take a look at the code below.

let log = console.log

let studentCourses = [
  { student: "John", course: "Computer Science" },
  { student: "Jane", course: "Engineering" },
  { student: "Billy", course: "Engineering" },
  { student: "Essyy", course: "Business Management" },
];

let hasElement = (course, obj) => obj.course === course
let engineeringStudents = studentCourses.filter((x) => hasElement("Engineering", x));
log(engineeringStudents);

/*Output:
[ { student: 'Jane', course: 'Engineering' },
  { student: 'Billy', course: 'Engineering' } ]

In the code above, you have a studentCourses[] array that holds several objects, each with a student name and course. The aim is to have a program that can filter students by their courses.

The line let engineeringStudents = studentCourses.filter((x) => hasElement("Engineering", x)); calls the Javascript filter method on the studentCourses array. The filter method takes a callback function that gets every item x in the array which is checked against the hasElement() function.

The hasElement() function takes two arguments, the element you want to filter and the item fetched from the array. It returns a true or false value. Values that evaluate as true are stored in the engineeringStudents variable and later logged in the console.

You have probably noticed that the hasElement() function is not curryable. To make it curryable, you will tweak the code as shown below.

function hasElement(course) {
  return function (obj) {
    return obj.course === course;
  };
}

let engineeringStudents = studentCourses.filter(hasElement("Engineering"));
log(engineeringStudents);

/*Output:
[ { student: 'Jane', course: 'Engineering' },
  { student: 'Billy', course: 'Engineering' } ]

But why write all that code when you can use a library like Lodash? To transform the hasElement() to a curryable function with Lodash, you would write your code as shown below.

let hasElement = _.curry((course, obj) => obj.course === course)

let engineeringStudents = studentCourses.filter(hasElement("Engineering"));
log(engineeringStudents);

/*Output:
[ { student: 'Jane', course: 'Engineering' },
  { student: 'Billy', course: 'Engineering' } ]

Pretty neat and clean, right? The hasElement() function is now curryable. That means when you invoke the hasElement() and pass “Engineering,” as an argumenthasElement("Engineering"), it will return a new function which in turn expects an argument object to check if it has the course “Engineering.” The new function is directly passed as the callback function to the filter method.

Why Currying? Are there any Advantages?

Now that you have a better understanding of function currying in Javascript, you might wonder, is there any advantage of currying functions?

Below are some of the currying pros.

  • Function currying allows a program to check if everything is available before moving to the next stage.
  • Currying enables you to avoid invoking a function with the same argument repeatedly.
    Take a look at the code below.
function itemVolume(l,w,h){
    return l x w x h;
}
itemVolume(50,70,100)
itemVolume(35,65,100)
itemVolume(60,40,100)

In the code snippet above, the itemVolume() function takes three arguments which it uses to calculate the volume of an item. However, you will notice that if all the items have the same height, you will still need to pass the height value when invoking the function multiple times. You can quickly solve that with currying, as shown below.


function itemVolume(h) {
  return function (w) {
    return function (l) {
        return h * w * l
    };
  };
}

const itemHeight = itemVolume(100);
itemHeight(45)(60);
itemHeight(30)(40);
itemHeight(65)(75);

The code above does the same thing (calculating volume) but uses function currying. The line const itemHeight = itemVolume(100); sets a specific height for all items, and you don’t have to pass the height value every time you invoke the function.

  • Function currying transforms a function with many responsibilities into smaller functions with a single responsibility each. That results in having pure functions in your code without side effects and less prone to errors.
  • Function currying is used in Javascript to come up with high-order functions.
  • Compared to the standard way of writing functions, function currying, especially when implemented with arrow functions, make your code more readable.

Currying vs. partial application

Up to this point, you clearly understand currying in Javascript. However, another concept that confuses most developers as it looks similar to currying is partial application.

  • Currying: As discussed above, currying refers to the process of transforming a single function that takes multiple arguments into a series of nesting functions, each taking a single argument.
  • Partial application: This refers to a situation where a function is supplied with fewer arguments than it needs and returns a function that takes the remaining arguments.

The code snippet below will give you a deeper understanding of partial application.

let log = console.log;
function sum(a, b, c) {
  return a + b + c;
}
log(sum(1,2,3))

/*Output:
6

The sum() function above takes three arguments and returns the sum. If you want to implement partial application in the above program, tweak your code as shown below.

function sum(a, b, c) {
  return a + b + c;
}

function partial(fn, ...args) {
  return function (...moreArgs) {
    return fn(...args, ...moreArgs);
  };
}

const lastArg = partial(sum, 1,2)
log(lastArg(3))

/*Output:
6

What is happening here?

First, we write our sum() function, which takes three arguments and returns the sum. Next, we will write another function – function partial(fn, ...args) – that takes a function (fn) as an argument and a list of arguments (…args). Note that you will use the spread operator here since you are unsure how many arguments will be passed.

The partial function will return another function – return function (...moreArgs) – that takes additional arguments (...moreArgs). In turn, this function will call the fn function and pass all the arguments – fn(...args, ...moreArgs).

The line const lastArg = partial(sum, 1,2) invokes the sum() function partially as you only pass two arguments instead of three (1, 2). The remaining argument is passed in the lastArg() function – lastArg(3).

Even though this might look similar to currying to the naked eye, it is a completely different concept.

Conclusion

This post has given you a detailed guide on currying in Javascript. However, if you feel that this currying concept is somehow hard to understand, practice using more examples and also try to implement currying in your projects.

Below are some ideas where you can implement currying when working with Javascript.

  • Manipulating the DOM
  • Working with event listeners
  • Creating a function that only takes a single argument

Was this article helpful? Is there any additional information that you feel was left out?

You can also share your thoughts by replying on Twitter of Become A Better Programmer or to my personal account.