Polyfill: Create your own curry()
Tags: javascript, programming, career, webdev
Published: 2022-09-10 07:19:25

Saw this question in an interview some time ago: 

Create a method curry that when passed in a function, will return a curried version of the function:

```
const join = (a,b,c) => {
  return `${a}_${b}_${c}`
}

const curriedJoin = curry(join);

console.log(curriedJoin(1)(2,3)); //1_2_3
console.log(curriedJoin(1,2)(3)); //1_2_3
console.log(curriedJoin(1)(2)()()(3)); //1_2_3
console.log(curriedJoin(1,2,3)); //1_2_3 

```

## What is currying?

Wikipedia says:

> In mathematics and computer science, currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument.

A function that takes multiple arguments is transformed into a series of functions that take single arguments.

## Initial approach

Based on the definition this is how the function is supposed to be structured:

```
const curry = (fn) => {

const curriedFunction = (...args) => {


};
return curriedFunction;
};
```

The function takes an argument function `fn` and returns a new function.
The returned function expects arguments, and for ease of handling `...args` [(Rest Operator)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) is used. It is a way to handle indefinite number of arguments. Now `args` is an array having all the function arguments.

## Returning a function

Every time the curried function is called, a function has to be returned. It is also necessary to keep track of the arguments passed at every step of the sequence. When we want to execute the function, we can call `fn` with `...args`.


```
const curry = (fn) => {
  
  const curried = (...args) => {
    let arr = [];
      arr = [...arr,...args];
      const innerFunc = (...innerArgs) => {
      arr =[...arr,...innerArgs];
        if(arr.length === fn.length){
          return fn(...arr);
        }
        else{
          return innerFunc;
        }
        
        
     };
      return innerFunc;
    } 
    return curried;
};
```

[`fn.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length) returns the number of parameters expected by `fn`. A javascript function can take as many arguments as passed, but this value will always return the number of formal parameters.

It is useful in the base condition. As soon as the length of the array is equal to the number of parameters expected, the callback function can be called.

## Edge conditions

The above solutions solve most of the cases except this:

```
console.log(curriedJoin(1,2,3));
```

To handle this, the function should have another check in case all the arguments are passed in the first go itself.

```
const curry = (fn) => {
  
  const curried = (...args) => {
    let arr = [];
   if(args.length === fn.length){
     return fn(...args);
   }
   else{
      arr = [...arr,...args];
      const innerFunc = (...innerArgs) => {
      arr =[...arr,...innerArgs];
        if(arr.length === fn.length){
          return fn(...arr);
        }
        else{
          return innerFunc;
        }
        
        
     };
      return innerFunc;
    } 
  }
  return curried;
}
```

## Summary

The question tests the solver's understanding of closures. It also relies on the fact that the solver is aware of the length property of the Function prototype, but that is not the main point. Since there is a lot of nesting it is a good way to check how clearly the solver thinks in complicated scenarios.

Let me know in comments how you would solve it?