Currying
Tags: functional, computerscience, javascript, php
Published: 2020-03-16 15:08:16

In mathematics and computer science, currying is a way of splitting a function which takes multiple arguments into a sequence of functions that take a subset of those arguments until all are provided and can be used to execute the original function.

For example if we had a function like this:

```javascript
function createPerson(name, age, occupation) {
  return {
    name,
    age,
    occupation
  };
}

console.log(
  createPerson("James", 26, "Senior Software Engineer")
);
```

We could also make something like this to generate the same output:

```javascript
function createPerson(name) {
  return function(age) {
    return function(occupation) {
      return {
        name,
        age,
        occupation
      };
    }
  }
}

console.log(
  createPerson("James")(26)("Senior Software Engineer")
);
```

This is useful in scenarios where you only have part of the data available for execution and wish to partially apply incoming data until all requirements are fulfilled. This is what makes currying and partial application two very related subject matters.

In this article we will write a higher order function to auto-curry any other function for us to avoid nested `return function` statements like we saw in the example above.

## Tests

```javascript
function add(left, right) {
  return left + right;
}

function createPerson(name, age, occupation) {
  return {
    name,
    age,
    occupation
  };
}

describe("Curry", () => {
  it("Should throw for invalid parameters", () => {
    expect(() => curry("string")).toThrowError(TypeError);
  });

  it("Should run as normal if all arguments are presented", () => {
    const curriedAdd = curry(add);
    const sum = curriedAdd(1, 2);
    expect(sum).toBe(3);
  });

  it("Should run if values are passed in via consecutive calls", () => {
    const curriedAdd = curry(add);
    const sum = curriedAdd(1)(2);
    expect(sum).toBe(3);
  });

  it("Should run if values passed in consecutive calls of varying length", () => {
    const curriedCreatePerson = curry(createPerson);
    const person = curriedCreatePerson("James")(26, "Senior Software Engineer");
    expect(person).toEqual({
      name: "James",
      age: 26,
      occupation: "Senior Software Engineer"
    });
  });
});
```

These tests are written in [Jest](https://jestjs.io/) and cover 3 primary cases for our auto-currying function:

1. If all values are present will the function run as if it hasn't been curried?
2. If I present the values in consecutive function calls, will it return as expected once all necessary values are supplied?
3. If I have multiple parts of data available to apply, can I do so without more function calls than is necessary?

In short, you can call the curried version of the function as often or as little as you like so long as the values from each call equate eventually to a minimum of those required by the function that was curried.

## Implementation

This implementation will introduce some oddities of the JavaScript language, specifically that when it comes to functions, JavaScript allows us to access a `length` property representing the amount of arguments required for that function.

For example if I were to run the following:

```javascript
function add(left, right) {
  return left + right;
}

console.log(add.length); // 2
```

We would see an output to the console of `2` since we require the `left` and `right` parameters to be present.

This is interesting and weird in my opinion although I am sure some others think this is totally a normal feature to have but I don't know... Anyway, I recommend reading the [MDN article on the function length property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length) to understand why and how this works.

For our `curry` higher order function function we use this property which is why I thought it relevant to bring up for those who may not be aware of it.

Anyhow, without further ado, here is the implementation I have chosen to go with for the `curry` higher order function:

```javascript
/**
 * @function curry
 * @description A function which can curry any another function
 * @see {@link https://en.wikipedia.org/wiki/Currying Wikipedia article about currying}
 * @param {Function} fn - The functions to curry
 * @returns {(Function|*)} A function to apply the remaining required aruments to or the return value of the provided `fn` when enough arguments are eventually provided
 */
function curry(fn, ...parameters) {
  if (typeof fn !== "function") {
    throw new TypeError(`Parameter 1 must be of type Function. Received: ${typeof fn}`);
  }

  if (parameters.length >= fn.length) {
    return fn(...parameters)
  }

  return (...args) => curry(fn, ...parameters, ...args);
}
```

In short, our implementation utilises the `length` propery to check if the `parameters` provided to the `curry` function equate to that of the requirements of the `fn` function. If the requirements were fulfilled, it runs the `fn` function with the `parameters` that were provided and returns it's value. 

If on the other hand there are not enough `parameters` available, a new function is returned which takes a set of `args`. When this new function is executed, we recursively run the `curry` function again passing in any previously provided `parameters` and the new incoming `args` as the new iterations value of the `parameters` argument. From here the cycle either breaks or is recursed again until all values that are required are provided and the `fn` that was originally provided can be executed and it's return value returned.

## Conclusions

Currying is a relatively simple thing once you wrap your head around it and plays a relatively big role in [Functional Programming](https://en.wikipedia.org/wiki/Functional_programming) due to it's ability to easily achieve partial application and split larger actions into smaller ones.

Currying is also a relatively common concept and so understanding how it works in your language of choice won't hurt, for example in [PHP](https://www.php.net/) I would rewrite the JavaScript implementation above, like so:

```php
function curry(string $fn, ...$parameters) {
  $reflector = new ReflectionFunction($fn);
  $requiredArgs = $reflector->getNumberOfParameters();

  if(count($parameters) >= $requiredArgs) {
    return call_user_func($fn, ...$parameters);
  }

  return function(...$args) use ($fn, $parameters) {
    return curry($fn, ...$parameters, ...$args);
  };
}
```

The code is almost identical but we need to use a few different language specific features such as the `ReflectionFunction` class that PHP gives us or that functions are passed as string references for example but generally speaking this is the same code with only some minor differences. We can even run the PHP example basically the same way we do the JavaScript version, like so:

```php
function add($left, $right) {
  return $left + $right;
}

$curriedAdd = curry("add");
$result = $curriedAdd(1)(2);
echo $result; // 3
```

How might you implement this in your language of choice? Let me know in the comments below!