DEV Community

Luke Inglis
Luke Inglis

Posted on

Function currying in JavaScript

Preface

I'm a big fan of functional programming. I'm not an expert by any means but I take any good opportunity to advance my learning and to apply FP ideas and practices in my own coding and design.

Currying in JavaScript

In my day to day work I'm a web developer working mostly with Rails and assorted JavaScript frameworks and libraries for front end. Fortunately for me JavaScript has a lot of features allowing you to program in a functional manner.

First class and higher order functions

One of the main things a language needs to support in order to be a Functional language is first class functions. This is to say that the language must treat functions as a data type which can be assigned to a variable just as any other type of data can be. Higher order functions go hand in hand with first class functions. A higher order function is simply a function which can take a function as argument or return a function as a value.

Currying functions

Currying a function is the process of taking a single function of multiple arguments and decomposing it into a sequence of functions that each take a single argument.1.

A simple example is a sum function like such

const sum = function(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

In order to curry this sum function we need to make it act a sequence of single arity functions. Because functions are first class in JavaScript we can have a curried sum take a single argument and return another function of one argument which adds it's argument to the argument of the first (outer) function. This would look like


const sum = function(a) {
  return function(b) {
    return a + b;
  };
}
Enter fullscreen mode Exit fullscreen mode

We can write this much more cleanly with ES6 arrow functions like so

const sum = (a) => (b) => a + b;
Enter fullscreen mode Exit fullscreen mode

This would be called in the slightly funky looking

sum(3)(2) // 5
Enter fullscreen mode Exit fullscreen mode

Clearly this in itself doesn't gain us anything. One of the more practical usages of currying is when you need to perform the same type of operation repeatedly with more than one input. This is particularly useful with predicate function. Here's an illustration using our old friend FizzBuzz2

let isDivisibleBy = (a) => (b) => b % a === 0;

let isFizz = isDivisibleBy(3);
let isBuzz = isDivisibleBy(5);

for(let number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]) {
  if (isFizz(number) && isBuzz(number))
    console.log('Fizz Buzz');
  else if(isFizz(number))
    console.log('Fizz');
  else if (isBuzz(number))
    console.log('Buzz');
  else
    console.log(number);
}
Enter fullscreen mode Exit fullscreen mode

Here isDivisibleBy is our curried function. For FizzBuzz we want to apply a common operation, divisibility checking, with more than one arugment, 3 and 5. Using currying we are able to compose isDivisibleBy into two more specific predicates isFizz and isBuzz.

Personally I find this if/else much more readable than say

if (number % 5 === 0 && number % 3 === 0)
  console.log('Fizz Buzz');
// ...etc.
Enter fullscreen mode Exit fullscreen mode

There is certainly more and better to be said about currying and its uses in JavaScript but I hope this is a useful introduction to the idea.

Any and all comments and suggestions for improvement welcome.

Footnotes


  1. https://en.wikipedia.org/wiki/Currying 

  2. https://en.wikipedia.org/wiki/Fizz_buzz 

Top comments (2)

Collapse
 
belidenikhil profile image
NikhilBelide

Great example!
Rest of the world is still stuck with a,b,c multiplication.

Collapse
 
hseritt profile image
Harlin Seritt

Always great to review this subject! Very good write-up, Luke!