Understanding Currying in JavaScript

Understanding Currying in JavaScript

A short yet detailed guide to Currying in JavaScript. We will see how currying works and how it will be useful in our work as software developers. Currying turns multi-argument functions into unary (single argument) functions. Currying's great in theory, but invoking a function for each argument gets tiring in JavaScript.

A short yet detailed guide to Currying in JavaScript.

Functional programming is a style of programming that attempts to pass functions as arguments(callbacks) and return functions without side-effects(changes to the program’s state).

So many languages adopted this programming style. JavaScript, Haskell, Clojure, Erlang, and Scala are the most popular among them.

And with its ability to pass and return functions, it brought so many concepts:

  • Pure Functions
  • Currying
  • Higher-Order functions

And one of the concepts we are going to look at here is Currying.

In this article📄, we will see how currying works and how it will be useful in our work as software developers.

What is Currying?

Currying is a process in functional programming in which we can transform a function with multiple arguments into a sequence of nesting functions. It returns a new function that expects the next argument inline.

It keeps returning a new function (that expects the current argument, like we said earlier) until all the arguments are exhausted. The arguments are kept "alive"(via closure) and all are used in execution when the final function in the currying chain is returned and executed.

Note: The term arity, refers to the number of arguments a function takes. For example,

function fn(a, b) {
    //...
}function _fn(a, b, c) {
    //...
}

function fn takes two arguments (2-arity function) and _fn takes three arguments (3-arity function).

So, currying transforms a function with multiple arguments into a sequence/series of functions each taking a single argument.

Let’s look at a simple example:

function multiply(a, b, c) {
    return a * b * c;
}

This function takes three numbers, multiplies the numbers and returns the result.

multiply(1,2,3); // 6

See, how we called the multiply function with the arguments in full. Let’s create a curried version of the function and see how we would call the same function (and get the same result) in a series of calls:

function multiply(a) {
    return (b) => {
        return (c) => {
            return a * b * c
        }
    }
}log(multiply(1)(2)(3)) // 6

We have turned the multiply(1,2,3) function call to multiply(1)(2)(3) multiple function calls.

One single function has been turned to a series of functions. To get the result of multiplication of the three numbers 1, 2 and 3, the numbers are passed one after the other, each number prefilling the next function inline for invocation.

We could separate this multiply(1)(2)(3) to understand it better:

const mul1 = multiply(1);
const mul2 = mul1(2);
const result = mul2(3);
log(result); // 6

Let’s take it one after the other. We passed 1 to the multiply function:

let mul1 = multiply(1);

It returns the function:

return (b) => {
        return (c) => {
            return a * b * c
        }
    }

Now, mul1 holds the above function definition which takes an argument b.

We called the mul1 function, passing in 2:

let mul2 = mul1(2);

The mul1 will return the third function:

return (c) => {
            return a * b * c
        }

The returned function is now stored in mul2 variable.

In essence, mul2 will be:

mul2 = (c) => {
            return a * b * c
        }

When mul2 is called with 3 as the parameter,

const result = mul2(3);

it does the calculation with the previously passed in parameters: a = 1, b = 2 and returns 6.

log(result); // 6

Being a nested function, mul2 has access to the variable scope of the outer functions, multiply and mul1.

This is how mul2 could perform the multiplication operation with variables defined in the already exit-ed functions. Though the functions have long since returned and garbage collected from memory, yet its variables are somehow still kept "alive".

You see that the three numbers were applied one at a time to the function, and at each time, a new function is returned until all the numbers are exhausted.

Let’s look at another example:

function volume(l,w,h) {
    return l * w * h;
}const aCylinder = volume(100,20,90) // 180000l

We have a function volume that calculates the volume of any solid shape.

The curried version will accept one argument and return a function, which also will accept one argument and return a function. This will loop/continue until the last argument is reached and the last function is returned, which will perform the multiplication operation with the previous arguments and the last argument.

function volume(l) {
    return (w) => {
        return (h) => {
            return l * w * h
        }
    }
}
const aCylinder = volume(100)(20)(90) // 180000

Like what we had in the multiply function, the last function only accepts h but will perform the operation with other variables whose enclosing function scope has long since returned. It works nonetheless because of Closure.

The idea behind currying is to take a function and derive a function that returns specialized function(s).

Currying in Mathematics

I kinda liked the mathematical illustration 👉Wikipedia gave to demonstrate further the concept of currying. Let’s look at it here with our own example.

If we have an equation

f(x,y) = x^2 + y = z

There are two variables x and y. If the two variables were given as x=3 and y=4, find the value of z.

If we substitute y for 4 and x for 3 in f(x,y):

f(x,y) = f(3,4) = x^2 + y = 3^2 + 4 = 13 = z

We get the result, 13.

We can curry f(x,y) to provide the variables in a series of functions:

h = x^2 + y = f(x,y)
hy(x) = x^2 + y = hx(y) = x^2 + y[hx => w.r.t x] and [hy => w.r.t y]Note: hx is h subscript x and hy is h subscript y. w.r.t is with respect to.

If we fix x=3in equation hx(y) = x^2 + y , it will return a new equation that have y as the variable:

h3(y) = 3^2 + y = 9 + yNote: h3 is h subscript 3

It is the same as:

h3(y) = h(3)(y) = f(3,y) = 3^2 + y = 9 + y

The value hasn’t been resolved, it returned a new equation 9 + y expecting another variable, y.

Next, we pass in y=4:

h3(4) = h(3)(4) = f(3,4) = 9 + 4 = 13

y being last in the variable chain, The addition op is performed with the previous variable x = 3 still retained and a value is resolved, 13.

So basically, we curried the equation f(x,y) = 3^2 + y to a sequence of equations:

3^2 + y -> 9 + yf(3,y) = h3(y) = 3^2 + y = 9 + y
f(3,y) = 9 + y
f(3,4) = h3(4) = 9 + 4 = 13

before finally getting the result.

Wow!! That’s some math, if you find this not clear enough 😕. You can read📖 the full details on 👉Wikipedia.

javascript programming developer web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Why Web Development is Important for your Business

With the rapid development in technology, the old ways to do business have changed completely. A lot more advanced and developed ways are ...

Important Reasons to Hire a Professional Web Development Company

    You name the business and I will tell you how web development can help you promote your business. If it is a startup or you seeking some...

What Garbage Collection in JavaScript Is and How It Works

JavaScript values are allocated when things are created (objects, Strings, etc.) and freed automatically when they are no longer used. This process is called Garbage collection.

What Javascript Spread Operator is, How It Works and How to Use It

JavaScript spread operator is one of the more popular features that were introduced in ES6. This tutorial will help you understand it. You will learn what spread operator is and how it works. You will also learn how to use it to copy and merge arrays and object literals, insert data and more.

Top 10 Web Development Trends in 2020 | Web Development Skills

Top 10 Web Development Trends in 2020 will provide you with a detailed list of the trends which are currently being noticed. Upskilling to these trends will help you in landing onto better jobs in 2020-2021.