Partial Functions in JavaScript
May 18th, 2013JavaScript (both the language itself and libraries such as Underscore) provides many functions that use closures. A closure is a block of code that is passed as an argument to a function or returned from a function. In JavaScript you pass in that code in the form of a function.
Consider the following example for calculating the 20% tip of an array of checks.
The map
function accepts a closure that in the example returns a 20% tip.
Rather than using an inline tip
function it makes sense to pass a reference to a defined function, so we can reuse the tip
function.
Probably you don’t always want to tip 20%. Sometimes you want to tip a little more, other times you may want to tip a little less. Therefore you want to pass in the percentage to tip
as an argument rather than tipping 20% all the time.
Adding the percentage as argument is of course simple. But now we can no longer pass the tip function into map since it needs an extra argument that map ain’t going to provide. Rather than using an inline function that calls tip
with 20%, let’s explore another possibility.
Partial Functions
Partial functions is a functional programming concept. A partial function takes a function and fewer arguments than normal. It returns a function that takes the remaining arguments. When called the returned function call the original function with both sets of arguments.
As JavaScript is a dynamic language that can create functions on the fly, it should be possible to implement this feature.
We need a function partial
that takes a function and a variable number of arguments for its input. That’s pretty easy considering that any function in JavaScript takes a variable number of arguments. These arguments can be accessed from the arguments
array.
[arguments
is not an actual array but an object that supports array lookups. It lacks most array functions (like map
), but we can call the functions from the array prototype using arguments
as their context.]
Then partial
must return a function that takes the remaining arguments and, as invoked, calls the original function with the combined argument arrays. Since partial
can only access arguments in form of an array we cannot call the original function (i.e. using parentheses or call
) but must apply
it instead. This way the array of arguments we pass to apply
is mapped to arguments of the original function.
Using partial
the general tip function can be passed into map as a 20%-tip function like this.
This partial
function only works for pure functions and not for a function that gets needs some state of the object it is in. This is due to the function being applied without a context.
Partial functions can offer a great deal of flexibility and can prevent a lot of adapter functions. Pay attention to the order of your arguments as JavaScript binds arguments by the order they are passed in. The example with the tip
function obviously wouldn’t have worked out if the percentage
argument was last.