Currying and Partial Functions in JavaScript

Currying

Currying has nothing to do with the spicy Indian dish; it comes from the name of the mathematician Haskell Curry. (The Haskell programming language is also named after him.) Currying is a transformation process — we transform a function. An alternative name for currying could be schönfinkelisation, after the name of another mathematician, Moses Schönfinkel, the original inventor of this transformation.

So how do we schönfinkelify (or schönfinkelize or curry) a function? Other functional languages may have that built right into the language itself and all functions are curried by default. In JavaScript we can modify the `add()` function into a curried one that will handle partial application. Let's take an example:

```// a curried add()
// accepts partial list of arguments
var oldx = x, oldy = y;
if (typeof oldy === "undefined") { // partial
return function (newy) {
return oldx + newy;
};
}
// full application
return x + y;
}

// test

// create and store a new function
```

In this snippet, the first time you call `add()`, it creates a closure around the inner function it returns. The closure stores the original values `x` and `y` into private variables `oldx` and `oldy`. The first one, `oldx`, is used when the inner function executes. If there's no partial application and both `x` and `y` are passed, the function proceeds to simply add them.

This implementation of `add()` is a little more verbose than needed, just for illustration purposes. A more compact version is shown in the next snippet, where there's no `oldx` and `oldy`, simply because the original `x` is stored in the closure implicitly and we reuse` y` as a local variable instead of creating a new variable `newy` as we did in the previous example:

```// a curried add
// accepts partial list of arguments
if (typeof y === "undefined") { // partial
return function (y) {
return x + y;
};
}
// full application
return x + y;
}
```

In these examples, the function `add()` itself took care of partial applications. But can we do the same in a more generic fashion? In other words, can we transform any function into a new one that accepts partial parameters? The next snippet shows an example of a general-purpose function, let's call it `schonfinkelize()`, which does just that. We use the name `schonfinkelize()` partially because it's a challenge to pronounce and partially because it sounds like a verb (using "curry" could be ambiguous), and we need a verb to denote that this is a transformation of a function.

Here is the general-purpose currying function:

```function schonfinkelize(fn) {
var slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function () {
var new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
};
}
```

The `schonfinkelize()` function is probably a little more complicated than it should be, but only because `arguments` is not a real array in JavaScript. Borrowing the `slice()` method from `Array.prototype` helps us turn `arguments` into an array and work more conveniently with it. When `schonfinkelize()` is called the first time, it stores a private reference to the `slice()` method (called `slice`) and also stores the arguments it was called with (into `stored_args`), only stripping the first, because the first argument is the function being curried. Then `schonfinkelize()` returns a new function. When the new function is called, it has access (via the closure) to the already privately stored arguments `stored_args` and the `slice` reference. The new function has to merge only the old partially applied arguments (`stored_args`) with the new ones (`new_args`) and then apply them to the original function `fn` (also privately available in the closure).

Now, armed with a general-purpose way of making any function curried, let's give it a try with a few tests:

```// a normal function
return x + y;
}
// curry a function to get a new function
// another option -- call the new function directly
```

The transformation function `schonfinkelize()` is not limited to single parameters or to single-step currying. Here are some more usage examples:

```// a normal function
function add(a, b, c, d, e) {
return a + b + c + d + e;
}
// works with any number of arguments
schonfinkelize(add, 1, 2, 3)(5, 5); // 16
// two-step currying
addOne(10, 10, 10, 10); // 41
```

When to Use Currying

When you find yourself calling the same function and passing mostly the same parameters, then the function is probably a good candidate for currying. You can create a new function dynamically by partially applying a set of arguments to your function. The new function will keep the repeated parameters stored (so you don't have to pass them every time) and will use them to pre-fill the full list of arguments that the original function expects.

More Insights

 To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.

First C Compiler Now on Github

The earliest known C compiler by the legendary Dennis Ritchie has been published on the repository.

HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

HTML5 Mobile Development: Seven Good Ideas (and Three Bad Ones)

Building Bare Metal ARM Systems with GNU

All you need to know to get up and running... and programming on ARM

Amazon's Vogels Challenges IT: Rethink App Dev

Amazon Web Services CTO says promised land of cloud computing requires a new generation of applications that follow different principles.

How to Select a PaaS Partner

Eventually, the vast majority of Web applications will run on a platform-as-a-service, or PaaS, vendor's infrastructure. To help sort out the options, we sent out a matrix with more than 70 decision points to a variety of PaaS providers.

More "Best of the Web" >>