Closures, Partial Application and Currying: Effective Functional JavaScript
Spices and other ingredients of a great curry
To use JavaScript to its full potential you have to embrace its strong functional programming base. We’re going to explore some crucial and powerful functional constructs: closures, partial application and currying that make JavaScript terse yet understandable.
Table of Contents
The basics
Functional programming is a programming paradigm that follows a more mathematical computation model. Let’s go through some basics to make your JavaScript more functional.
Declarative programming
Functional programs tend to be declarative (as opposed to imperative), that’s a case of telling the compiler what you want instead of how you want it.
const list = [ 1, 2, 3 ];
// imperative style
const imperative = list[0];
// declarative style
const declarative = firstElement(list);
In the above code snippet we’re trying to get the first element of list, the declarative example says what we want, firstElement can do whatever it likes as long as it returns the first element of the passed parameter. Whereas in the imperative style, we say I want index 0 of list explicitly. In JavaScript and at this program size, this doesn’t make a massive difference.
To build functional programs, we should prefer the declarative style and avoid mutation.
Recursion and higher order functions
There are no loops in functional programming, just recursion and higher order functions.
Mechanisms such as pattern matching allow for easier recursive function declarations. In ECMAScript 6 (the 2015 edition of the standard JavaScript is based on) we’ve added destructuring to the toolbox, which is a basic pattern matching that works for lists. You can read more about it here. Recursion in JavaScript with ES6, destructuring and rest/spread *The latest ECMA standard for JavaScript (ECMAScript 6) makes JavaScript more readable by encouraging a more declarative…*hackernoon.com
Higher order functions allow you to traverse iterable collections (Arrays). In JavaScript we have Array#map, Array#filter and Array#reduce. Each of these takes a function as an argument. This is possible because we have first-class functions in JavaScript, which means you can pass them around like any other type of variable :).
Lambdas (anonymous functions)
In JavaScript we can declare lambas (anonymous functions), which is quite handy considering the API of a lot of libraries expects a function as a parameter. We can just declare the function inline. It might mean a bit of a indentation/bracketing problem but inlining until you can generalise or refactor is actually great.
[ 1, 2, 3 ].map(function(el) {
return el * 2;
});
Closures
Here are some >140 character explanations of closures, thanks to Mateusz Zatorski for asking and his esteemed followers for answering :).
We can use closures to put state inside an outer function while having access to that state in an inner function. That state is not global but still accessible to child functions.
function outerFunction() {
const someState = { count: 0 };
return {
increment: function() {
someState.count++;
},
getCount: function() {
return someState.count;
}
}
}
const counter = outerFunction();
counter.increment();
counter.increment();
counter.getCount(); // 2
counter.increment();
counter.increment();
counter.getCount(); // 4
someState; // ReferenceError: someState is not defined
The state (someState
) isn’t global since the last statement returns an error. It is however available to the functions it returned, because they can “see” someState, it’s in their lexical scope.
Function application
Function application is the first “hardcore” functional programming concept we’re going to introduce today. It’s a concept that comes from the mathematics world.
A function application, in JavaScript, can look like a function call but doesn’t have to be.
function someFunc(arg1, arg2) {
return arg1 + arg2;
}
// function call
someFunc(1, 2); // 3
// different ways to apply a function
someFunc(1, 2); // 3
someFunc.apply(this, [ 1, 2 ]); // 3
someFunc.call(this, 1, 2); // 3
A function call is an imperative construct whereas a function application belongs to the realm of functional programming and mathematics.
In JavaScript you can even use apply and call to define what this will be set to during the application.
Partial application
Partial application is when you apply some of the required parameters of a function and return a function that takes the rest of the parameters.
We’re going to flip the parameters to the map function. Instead of taking parameters (list, fn)
it’s going to take (fn, list)
. This is to illustrate the value of partial application.
function functionalMap(fn, list) {
return list.map(fn);
}
function partialFunctionalMap(fn) {
return function(list) {
return functionalMap(fn, list);
}
}
// Example 1
// Let's apply all the arguments at once
functionalMap(x => x * 2, [ 1, 2, 3 ]);
functionalMap(x => x * 2, [ 2, 3, 5 ]);
// Example 2
// Let's apply them one at a time
const doubleListItems = partialFunctionalMap(x => x * 2);
doubleListItems([ 1, 2, 3 ]);
doubleListItems([ 2, 3, 5 ]);
What the code does in example 1 is less obvious than in example 2. You have to read what the lamba does instead of being told by the variable function name.
This is something we can use in places like React event handlers.
class MyComponent extends React.Component {
partialHandleLinkClick(type, activeType){
return function(e) {
const hasKeyboardModifier = e.ctrlKey || e.shiftKey || e.altKey || e.metaKey;
updateType(type, activeType, hasKeyboardModifier);
};
}
render() {
const types = [ 'Foo', 'Bar', 'Baz' ];
return (
<div>
{
types.map( (type, i) => {
<a key={i} href="#"
onClick={this.partialHandleLinkClick(type, this.props.activeType)}>
{type}
</a>
})
}
</div>
);
}
}
Now if we went the Object-oriented route, we would use .bind
partialHandleClick
function to the component instance (this
) and to be able to access this.props.activeType
from inside partialHandleClick
.
We’re trying to leverage functional programming, so no accessing this from all the way inside an event handler.
We get to store some information that we can get at .map
time (which type is this handler for).
When the event triggers, we get the final parameter we need e
(the event object) and the handler can finish applying.
Currying
A curried function is a function that you apply 1 parameter at a time.
function partialFunctionalMap(fn) {
return function(list) {
return functionalMap(fn, list);
}
}
partialFunctionalMap
is curried.
In the event handler example partialHandleLinkClick
isn’t, since the first application provided 2 parameters.
We could rewrite it though.
function curriedHandleLinkClick(type){
return function(activeType) {
return function(e) {
const hasKeyboardModifier = e.ctrlKey || e.shiftKey || e.altKey || e.metaKey;
updateType(type, activeType, hasKeyboardModifier);
};
};
}
And we would use this.curriedHandleLinkClick(type)(this.props.activeType)
instead of this.partialHandleLinkClick(type, this.props.activeType)
.
This isn’t as pretty in JavaScript as in other languages since we’re replacing (arg1, arg2, arg3)
with (arg1)(arg2)(arg3)
.
Currying and partial application
Currying is strict: a curried function always applied 1 parameter at a time. Partial application is not this strict.
A curried function tends to be partially applied but a partially applied function does not have to be curried.
This means we can automate the currying process.
In JavaScript we can use libraries to curry functions with multiple arguments. Lodash has a curry function and so does Ramda. They take a function and when applied with a parameter either returns if all required arguments are present or returns a curried function that accepts the rest of the arguments.
You can also write your own by accessing the arguments object of the function and using Function#apply. Here are a couple of tutorials that take you through this process.
Currying in JavaScript A technique using partial evaluation
Currying in JavaScript- Kevin Ennis
Some languages like Haskell are auto-curried. This means that if the function application does not provide the required number of parameters, it will return a function which will accept the rest of the parameters one at a time, just like the Lodash and Ramda curry functions do. Another cool thing in Haskell is that partial application looks like non-partial application and curried function calls aren’t ugly, since the separator for parameters is a space.
times a b = a * b
times 1 2
double = times 2
Effective Functional JavaScript Recipe
Use and abuse closures, partial application and currying.
This will enable you to compose your functions and write code that is extremely terse without losing readability.
Get The Jest Handbook (100 pages)
Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library.
orJoin 1000s of developers learning about Enterprise-grade Node.js & JavaScript