Instead of explaining to you what closure is, I’m going to show you some examples of how closure is used and walk you through the process of designing your application to take advantage of closure.
Here we go!
What is a Closure?
A closure is a way to access and manipulate external variables from within a function.
I like to think of a closure as a feature of the programming language to let us do cool things such as:
Let’s try a couple of things based on the function we created in the recursion example:
So far so good…
…Uh oh what happened?
incrementUntilalso maintains a closured reference to
numand can read and modify it. The scope of
windowif you typed this example as-is directly into the browser console.
incrementUntilis being executed inside of
myFun2, it didn’t modify the
myFun2’s scope because
incrementUntilonly recognizes the
numthat was inside of its parent’s scope when it was first created (e.g.,
window). It doesn’t recognize the
numinside of the caller,
myFun2, because it doesn’t maintain a closured reference to its caller’s scope.
Here’s how we can fix
myFun2 so it can leverage the
incrementUntil function to modify the
num inside of its own scope.
The “fix” for
myFun2 seems to work fine but it lends itself to a lot of duplicate code. What if we have to increment variables inside of other functions? It’s not good practice to copy-paste the same function/code into multiple places. Let’s refactor our
incrementUntil function using partial application:
incrementUntil function does not read or modify anything outside of its own scope so it’s a pure function, which illustrates a core principle of functional programming. You call the function as follows:
incrementUntil(max)(num), which reads “increment until
max starting from
A really nice thing about partial application is that we can partially evaluate the final solution by providing our function a subset of the arguments it needs. Then we can save the intermediate solution to a variable so we can save ourselves some processing time by eliminating the need to evaluate the same intermediate solution every time we call the function to do similar things (assuming your programming language supports this kind of optimization).
Here’s what I mean by that in code:
What’s happening in the code above is that you created a closure to keep the value passed to the function
multThenAdd even after the inner function is returned. The inner function that is being returned is created within an outer function, making it a closure.
The above code is equivalent to the following in ES6:
var multThenAdd = num => mul => add => num * mul + add
Quite elegant but the syntax could seem really strange for someone coming from an imperative language background.
Now you’ve seen partial application in action, here’s a high level discussion on the concept of partial application (also called currying by some).
Partial application is basically a design pattern where your function returns another function that takes an argument. For example, you can call your function like this:
myFun(arg1)(arg2), which is equivalent to:
const myFun2 = myFun(arg1)
Partial application is a powerful design pattern because you can continuing chaining things like
myFun(arg1)(arg2)(arg3)… What’s happening here is akin to an assembly line in a factory: One argument at a time is applied to
myFun to evaluate a better and better partial solution until all the arguments are applied to provide a complete solution.
Here’s an actual piece of code I wrote for a Node/Express app that uses the partial application pattern:
Here are some resources that that inspired me to create the content of this article: