A closure is a function which has captured ("closed over") one or more of the variables that were in scope when the function was defined.

There are several similar ways to implement closures. This is best understood by example. I will use pseudocode here.

Contents

Explicit capture

In some languages, you have to explicitly state which variables you want to capture.

Explicit capture by value

var x = "chips" var more_spam = function () capture (x) { x = x + " and spam" print(x) } more_spam() // "chips and spam" more_spam() // "chips and spam" x = "bacon" more_spam() // "chips and spam"

Notice how every invocation of more_spam begins with a variable x available, whose value is always "chips" at first. This is because we have captured x 's value.

Meanwhile, the original x can be reassigned freely.

Explicit capture by reference

In a programming language which captures by reference, the same pseudocode yields different results.

var x = "chips" var more_spam = function () capture (x) { x = x + " and spam" print(x) } more_spam() // "chips and spam" more_spam() // "chips and spam and spam" x = "bacon" more_spam() // "bacon and spam"

Here, more_spam 's x and the original x are the same variable; modifying one modifies the other. This is because we have captured x by reference.

Interestingly in this case, it's possible for x to drop out of scope even though more_spam hasn't and is still callable. When you call more_spam() , you will get the correct behaviour, because x still exists with its correct value, even though it is no longer directly accessible.

Note

Some languages allow you to select whether you capture by reference or by value, depending on which syntax you use when you declare the function.

Implicit capture

In some languages, the explicit capturing syntax doesn't exist. You just write:

var x = "chips" var more_spam = function () { x = x + " and spam" print(x) } x = "bacon" more_spam() // "chips and spam" if capturing by value // "bacon and spam" if capturing by reference

Here, more_spam captures x automatically, without being told. In fact, more_spam captures every available lexical variable, of which there could be many more beside x !

This can sometimes be problematic. If you want to use a variable named x inside your function, but you don't want to capture the x from outside it, you must remember to declare a brand new variable named x inside your function:

var x = "chips" var more_spam = function () { var x = "more spam" print(x) } x = "bacon" more_spam() // "more spam" every time

A classic pitfall

Use caution when creating closures in a loop. If you capture the loop variable by reference, watch what happens:

var more_food = {} for var food in ["eggs", "chips", "spam"] { more_food[food] = function() { print("more " + food) } } more_food["eggs"]() // "more spam" more_food["chips"]() // "more spam" more_food["spam"]() // "more spam"

Here, all the closures have captured references to the same loop variable, food . After the loop is over, the value of this variable is "spam" , no matter how it is accessed.

This gotcha is most often seen in JavaScript, but also appears in Python.