About Closures
In programming languages, a closure is an abstraction of an expression in an environment; the expression may contain free variables which are given meaning by the values bound to them in the environment.
The programmer can generally treat a closure as they would any other value: they can store it in a variable, pass it as an argument to a function, and return it as the return value of a function. Language constructs with this property are sometimes referred to as "first-class."
The closure is almost always a function value which can be called as if it were it were any other function or procedure. (Function values are also called lambda functions after an analogous construct, the abstraction, in Church's lambda calculus.) However, closures over other data types, for example entire modules, are possible.
A closure is different from a "function pointer" you might find in a language like C, because a closure has access to variables in the environment associated with it. This environment is usually the set of all variables that are "in scope" at the point in the program where the closure is created.
Since the environment of a closure may contain variables local to the function in which it is created, and since the closure may be returned as a value from that function, it may outlive the local variables referred to by its environment. For this reason, the language (and by extension its implementation) must ensure that those values continue to exist for as long as the closure itself exists, for example by allocating them on the heap instead of on the call stack.
This is where the term "closure" comes from: it "closes over" the variables in its environment. Note, though, that this use of the word "closure" has no relationship to the mathematical notion of closure (which basically means to keep doing something over and over until there is nothing more that will change.)
Closures seem to be one of those things that programming language designs and/or implementations have trouble with:
- LISP was the first language to promote functions as values, but it represented functions as lists and used dynamic binding to associate values with variables. This was a mess, and it took a long time for it to get better. Nowadays, Scheme has proper closures, and is a much more attractive choice overall.
- Javascript has closures, but they're notorious for leaking. Partly this is a consequence of the difficulty of interpreting the definitions of the DOM — what should and what shouldn't stick around for how long — but it is also due to the inadequacy of some vendors' garbage collection implementations.
- As of this writing, Python's closures are limited to a single expression. This may be a syntactic problem rather than a semantic one, but it is still something of an annoyance.
- By overloading the
()operator, it's possible to make closure-like objects even in C++. But if you try this, you'll soon appreciate why, in most languages, closures are garbage collected: if you have to explicitly reason about when the free variables will no longer be needed, you're not much better off from using function pointers. - Java, on the other hand, does have garbage collection, but doesn't have closures; instead, what you get to do is to create an instance of an anonymous class with a single method on it and initialize the member variables of that class with the values you want that method to close over. What fun!