### What is currying?

**Currying** is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument.

So currying transforms `fn(a, b, c…n) to fn(a)(b)(c)…n)`

. Let’s dive right in to an example.

```
const sum = (a, b) => a + b;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)); // = 3
```

The `curriedSum`

function converts the sum function into a sequence of two functions since the original sum function needs two arguments.

### Naive implementation

Based on the above example, we can implement a naive version of the curry function. So `curriedSum`

returns a function which accepts one argument `b`

. This is passed as the second argument to the function being curried. The first argument is stored in the function closure.

```
function curry(fn) {
return function (a) {
return function (b) {
return fn(a, b);
};
};
}
```

### Currying with variadic arguments

The previous implementation has a few problems

- It only works for functions which accept 2 arguments.
- The context value is not being propagated accurately.

Let’s try implementing a generic currying function which supports variadic arguments.

There are a couple of key insights behind the new implementation.

- Function.length returns the arity of the function. The arity of a function is the number of parameters expected by the function.

For example, consider this multiply function which returns the product of three numbers;

```
const multiply = (a, b, c) => a * b * c;
console.log(multiply.length); // 3
```

- We have to keep collecting arguments until we have enough arguments, i.e. till the number of arguments are greater than or equal to the arity of the function.

```
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
// Execute the original function when we have enough arguments
return fn.apply(this, args);
} else {
return (...nextArgs) => curried(...args, ...nextArgs); // otherwise keep on adding arguments
}
};
}
```

We can use bind for a more concise implementation.

```
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return curried.bind(this, ...args);
}
};
}
```

### Infinite sum

This happens to be a popular interview question based on recursion. So here’s the infinite sum function that we have to implement

```
sum(1)() // 1
sum(3)(2)() // 5
sum(1)(2)...(n)() // (1 + 2 + 3 ...n)
```

We can make some observations based on the above example

- The sum function returns the sum when we call it with undefined.
- If the function is called with a valid number another function is returned

```
const sum = (a) => {
return (b) => {
if (b === undefined) {
return a;
} else {
return sum(a + b);
}
};
};
```

### Infinite sum with variadic arguments

`sum(1, 2)(3)(4, 5)(); //15`

This is a bit more tricky. We are not dealiing with single arguments anymore.Try implementing this on your own before checking the solution.

## Solution

```
const sum = (...args) => {
return (...moreArgs) => {
if (moreArgs.length === 0) {
return args.reduce((a, b) => a + b);
} else {
return sum(...args, ...moreArgs);
}
};
};
```

### Currying with placeholder support

We are not done with currying yet, currying with placeholder support is something I might tackle in the future.