Let's Write: An Auto-Currying Higher Order Function
Tags: javascript, beginners, tutorial, node
Published: 2019-06-25 13:37:33

---
title: Let's Write: An Auto-Currying Higher Order Function
published: true
description: A simple and elegant 8-line solution.
tags: javascript, beginners, tutorial, node
---

I've been working on a project lately that involves writing a **lot** of callback functions, and some of them were getting pretty large. I decided to move as many of them as possible to separate modules to keep things small and relatively simple, but noticed that a lot of them depended on the parent function's scope. Functions in Javascript can't inherit the scope of something that they can't see. The easy way to fix a problem like this would just be to write a function that accepts the scope variables needed and then returns the callback function. This works because the returned callback function will inherit the scope of the parent (the passed variables). So something like this:

```javascript
const helloCallback = (instanceArg1, instanceArg2) =>
  (callbackArg1, callbackArg2) => {
    // Both instance args and callback args are in scope here!
  }

export default helloCallback
```

would be called like this in a listener in a separate module:

```javascript
import helloCallback from './helloCallback'

pretendAPI.onMessage(helloCallback(arg1, arg2))
```

It's a pretty simple and elegant solution! In the functional programming world, we call something like this *currying* (using this very loosely). True currying is where you split all of your function arguments over consecutive functions like Russian dolls. It looks like this:

```javascript
const helloCallback = instanceArg1 => instanceArg2 => callbackArg1 => callbackArg2 => {
  // all the variables are in scope!
}
```

This wasn't really optimal for what I needed though, so I just split my function over two different levels. 

For the hell of it, I decided to write my own function that would automatically curry any function. It would be used like this:

```javascript
const curried = curry((one, two, three, four) => console.log(one, two, three, four))
```

and could be called in any of these ways:

```javascript
curried(1)(2)(3)(4)
// Output: 1 2 3 4
curried(1, 2)(3, 4)
// Output: 1 2 3 4
curried(1, 2, 3, 4)
// Output: 1 2 3 4
```

And did I mention that it's only 8 lines long? Let's see how I wrote it.

***

There's a few pieces of information we need to know before we're able to write this `curry` function. First, what the hell is going on here? If we look at how the function is used, we can see that `curry` accepts in a function and then returns another function. There's an important thing to note here: the function that's returned *is not the same as what we passed in*. The function that's returned will either return the value of our original function with all of the arguments somehow magically applied, or it will return *another function that accepts more arguments in*. It might not be immediately obvious at first, but there's some kind of recursion going on in the `curry` function because we're returning a **different number of functions depending on the inputs to each previous function**.

With this in mind, we can start writing the skeleton of the `curry` function:

```javascript
const curry = functionToCall => {
  const recursiveSomething = () => something => {
    if (someCondition) return functionToCall(someArgs)
    else return recursiveSomething()
  }
  
  return recursiveSomething()
}
```

Let's look at this line by line. Our `curry` function accepts in an argument called `functionToCall` that we'll eventually call (great naming, amiright?). Then on the next line, we define a recursive function that returns another function. The function name is just used here so that we're able to recursively return functions as needed; as far as I know, it isn't possible to return anonymous functions that can be called recursively in Javascript. The returned function accepts in some arguments, and depending on `someCondition` we'll either return `functionToCall` with some arguments passed down to it or we'll return the results of a call to `recursiveSomething`, which is the function we're currently in. Last, we call `recursiveSomething`, returning our conditional-return function mess.

This may look pretty complicated, but we've actually got half of the function written. All that's left to do is fill in the blanks. The main problem we're trying to solve here is **argument storage**: we need some place to put all of the arguments we're going to receive so that we can pass it down to our "callback function" in one go. The easiest way to do this is to just use a [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), an array to store all of the arguments in, and then just spread that array over the `functionToCall`'s arguments when we call it:

```javascript
const curry = functionToCall => {
  let argumentsArray = []
  const recursiveSomething = () => (...args) => {
    argumentsArray = argumentsArray.concat(args)
    if (someCondition) return functionToCall(...argumentsArray)
    else return recursiveSomething()
  }
  return recursiveSomething()
}
```

Going through the lines we added, we can see that we added an array `argumentsArray` that's outside of the `recursiveSomething` function. This is important because it's in the scope of not only the root `recursiveSomething` return function, but *all future returned functions*. In the return function, we added a rest parameter (allows our function to accept in unlimited arguments and puts them in an array), and then concatenated that with the `argumentsArray`. Last, we used [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to apply the arguments in the array to `functionToCall` when we call it.

This is great, we're actually really close to finishing our auto-curryer! We just need to fill in when we'll call `functionToCall`, or the **base case** for our recursive function. We want to call `functionToCall` if and only if we have all of the arguments we need to actually call it. Functions in Javascript have a [length property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length), so we can use this to check whether the length of `argumentsArray` is equal to the number of arguments expected by the function:

```javascript
const curry = functionToCall => {
  let argumentsArray = []
  const recursiveSomething = () => (...args) => {
    argumentsArray = argumentsArray.concat(args)
    if (argumentsArray.length === functionToCall.length) return functionToCall(...argumentsArray)
    else return recursiveSomething()
  }
  return recursiveSomething()
}
```

And that's it! We can now pass `curry` a function and it'll automatically curry all of the arguments for us thanks to the magic of recursion! Not bad for only eight lines. If you want, you can also add a few more checks to support zero argument functions and to make sure you call the function correctly:

```javascript
const curry = functionToCall => {
  if (functionToCall.length === 0) return functionToCall;
  let argumentsArray = [];
  const recursiveSomething = () => (...args) => {
    if (
      (args.length === 1 && argumentsArray.length + 1 > functionToCall.length) ||
      (argumentsArray.length === 0 && args.length > functionToCall.length) ||
      args.length + argumentsArray.length > functionToCall.length
    )
      throw new Error("Wrong number of arguments received");
    argumentsArray = argumentsArray.concat(args);
    if (argumentsArray.length === functionToCall.length) return toCall(...argumentsArray);
    return recursiveSomething();
  };
  return recursiveSomething();
};
```