What is Function Currying in JavaScript and When to Use It
Tags: javascript, webdev, beginners, programming
Published: 2020-12-21 20:39:34

Currying is a way of building functions in a way that it is possible to call them with arguments one by one, instead of all of them at once. It will allow us to create new functions, which have some arguments already remembered. Currying helps with creating specialized functions based on general ones, ex. `getName`, `findId`, `joinWithSpaces` from `get`, `find`, `join`. It helps reducing code duplication.

## Creating a curried function

Let me start with very simple example, `sum` function in curried form:

```jsx
function sum(a) {
	return function(b) {
		return a + b;
	}
}

// using arrow function

const sum = a => b => a + b;
```

Looks strange at first sight, but let me explain it.

After calling `sum(5)` it won't return a number, but a new function:

```jsx
function(b) {
	return 5 + b; // a was changed to 5
}

// using arrow function

b => 5 + b;
```

Only after we call it the second time we will get the final result - sum of two numbers.

```jsx
function sum(a) {
	return function(b) {
		return a + b;
	}
}

// using arrow function

const sum = a => b => a + b;

const addTo5 = sum(5); // function(b) { return 5 + b }

addTo5(3); // 8
// is the same as
add(5)(3); // 8
```

Summing up, we created specialized function `addTo5` which has only one purpose - adding some number to 5. Function `sum` is more general.

## When to use the curried function

Let's see another curried function, which you might use in your application. Function `get` will take `key` name, return a function which takes `object` and in the end return a value for provided `key`. One use-case if using it as an argument for `Array.map`

```jsx
function get(key) {
  return function(obj) {
    return obj[key];
  }
}

// using arrow function

const get = key => obj => obj[key];

const getName = get('name');

const users = [{ name: 'John' }, { name: 'Emma' }];

const namesList = users.map(user => user.name); // normal way
const namesList = users.map(getName); // using specialized function
const namesList = users.map(get('name')) // using general function
```

As you can see this example is more practical. Because `object` is the last argument, we can pass this "unfinished" function to `map`, which calls this function with object. As a result we get value of `name` from the object.

Notice how more readable is this example when using `get` function -  `users.map(getName)`, you immediately understand what this code fragment does.

## Good practices of creating curried functions

When creating your own curried function you should follow one important rule.

Always leave the source of data as the last argument. To determine the order of other "configuration" arguments, think about function use-cases.

Let's take a look at the `get` function where source of data (`object`) is NOT the last argument.

```jsx
function get(obj) {
  return function(key) {
    return obj[key];
  }
}

// using arrow function

const get = obj => key => obj[key];

const users = [{ name: 'Adam' }, { name: 'Maciej' }]

const namesList = users.map(user => get(user)('name'))
```

As you can see using `get` function in this form doesn't make sense. And you can't really create a specialized function since you don't have access to the object yet. It is a good practice to leave the source of data as the last argument, because looking at the use-cases it usually comes at the end when executing the code.

## Creating curried functions from standard function

In JavaScript world we are not used to curried functions, but looking at the use-cases it looks very promising. Actually we can create a function which is both curried and not.

```jsx
function add(...args) {
  if (args.length === 1) {
    const [a] = args
    return function(b) {
      return a + b
    }
  }
  const [a, b] = args
  return a + b
}

add(5, 3) // 8
add(5)(3) // 8
```

If `add` is called with one argument `args.length === 1`, then we return new function where first argument is remembered, just like we did before. But if we call it with two arguments, it will just add them and return a sum.

You have to admit that it is very impressive, but the definition of this function is very complicated now and it's only summing up two numbers.

Thankfully there is a helper function which will help us with it:

```jsx
function curry(argsLength, originalFunction) {
  function next(prevArgs) {
    function curriedFunction(nextArgs) {
      const allArgs = [...prevArgs, ...nextArgs]
      if (allArgs.length >= argsLength) {
        // all arguments are provided, call the function
        return originalFunction(...args);
      }
      else {
        return next(allArgs)
      }
    }
  }
  return next([])
}
```

It looks even more complicated but with it, we can simply transform the standard function into a curried one. Just remember that the first argument of `curry` is the number of arguments it can take, and the second one is the function itself;

```jsx
const add = curry(2, (a, b) => a + b);

const addTo5 = add(5);

add(5, 3) // 8
addTo5(3); // 8
add(5)(3); // 8
```

Now you don't have to worry about how many arguments you call the function with. You call the function like you did before you got to know about currying or call the function, by one argument at a time.

---

I'm regularly publishing my insights on web development. 
Consider [subscribing to my newsletter](https://slawkolodziej.com/newsletter).
Visit my blog at [slawkolodziej.com](https://slawkolodziej.com) to find out more interesting content.
Follow me on [Twitter](https://twitter.com/slawkolodziej).