Yeison Daza
3 min read

Currying in JavaScript

One of the principles every programmer tries to follow is DRY (Don’t Repeat Yourself). With currying, we’ll see how applying this to our functions is pretty simple and useful.

The way we normally write our functions is:

//ES2015
const divisible = (num, mod) => num % mod;

//ES5
var divisible = function(num, mod) {
  return num % mod;
}

To execute this function, we need to pass two arguments. But if we wanted to have a function that exclusively checks whether a number is even, we’d have to write a new function. This is where having a curried function comes in handy.

But before understanding how a curried function works, we need to know a few concepts.

Functions are first-class citizens, meaning functions are objects — they can be passed as arguments, stored in variables, and returned inside other functions. Higher-order functions in JavaScript

A closure is when a function is able to remember and access a lexical scope, even when the function is executed outside of that lexical scope. Understanding closures in JavaScript

If a function receives more than one parameter, it can be rewritten as a function that takes one parameter and returns a function, which in turn receives a parameter and returns the result. Lambda calculus in JavaScript

What is Currying?

Currying is being able to call a function with fewer parameters than it expects. It returns a function that waits for the remaining parameters and then returns the result.

This way, we could rewrite the function from the beginning as:

//ES2015

const divisible = mod => num => num % mod;

//ES5

var divisible = function (mod) {
  return function (num) {
    return num % mod;
  }
}

To call this function, we have two options:

  • Pass all arguments by executing the functions:
divisible(10)(2)
  • Pass one argument and receive a function that remembers that argument:
const divisibleEn3 = divisible(3);

divisibleEn3(10)

As you can see, writing a curried function isn’t complicated, but we could make it feel a bit more natural — like how we write any regular function.

For this, we can use Lodash or Ramda, which have a curry method that lets us curry any function like this:

import { __, curry, map } from 'ramda';

const composeNombre = curry(
  (primer, apellido) => `${primer} ${apellido}`
);

const familiaJaimes = composeNombre(__, 'Jaimes')

const nombres = ['Juan', 'Camilo', 'Miguel']

console.log(map(familiaJaimes, nombres))

Let’s look at a more practical example taken from the Mostly adequate guide to functional programming:

import { curry } from 'ramda';

// Estas funciones las puedes conseguir dentro de Ramda o Lodash

var match = curry(function(what, str) {
  return str.match(what);
});

var replace = curry(function(what, replacement, str) {
  return str.replace(what, replacement);
});

var filter = curry(function(f, ary) {
  return ary.filter(f);
});

var map = curry(function(f, ary) {
  return ary.map(f);
});


var hasSpaces = match(/\s+/g);

hasSpaces("hello world");
// [ ' ' ]

hasSpaces("spaceless");
// null

filter(hasSpaces, ["tori_spelling", "tori amos"]);
// ["tori amos"]

var findSpaces = filter(hasSpaces);
// function(xs) { return xs.filter(function(x) { return x.match(/\s+/g) }) }

findSpaces(["tori_spelling", "tori amos"]);
// ["tori amos"]

Advantages of Currying

  • We can create new functions simply by calling our base functions with some parameters.
  • We can transform any function that works with a single element into one that works with a list by wrapping it in a map.
  • We can write small pieces of code that are easier to reuse.
  • They’re easy to reason about.
  • Writing curried functions will allow us to compose functions.