Closure (computer science)In programming languages, a closure is an abstraction representing a function, plus the lexical environment (see static scoping) in which the function was created.
Closures are typically implemented with a special data structure that contains a pointer to the function code, plus a representation of the function's lexical environment (i.e., the set of available variables and their values) at the time when the closure was created.
Closures typically appear in languages that allow functions to be "first-class" values --- in other words, such languages allow functions to be passed as arguments, returned from function calls, bound to variable names, etc., just like simpler types such as strings and integers.
fun f(x) = x + 1;Such a function may "capture" name/value bindings from its enclosing environment, producing a closure. For example, in the code fragment:
val x = 1; fun f(y) = x + y;the closure data structure representing f contains a pointer to the enclosing environment, in which x is bound to 1. Therefore, f will always return its argument plus 1, even if the environment in which it is applied has a different value for x. Therefore, consider the code fragment:
let val x = 1; fun f(y) = x + y; in let val x = 2; in f(3) end endIn this code, the call f(3) occurs in an environment (the inner let) where x is bound to 2. However, the closure for f was constructed in an environment (the outer let) where x is bound to 1. Therefore the result of the call f(3) is 4, not 5.
Closures have many uses:
- Designers of software libraries can allow users to customize behavior by passing closures as arguments to important functions. For example, a function that sortss values can accept a closure argument that compares the values to be sorted according to a user-defined criterion.
- Because closures delay evaluation --- i.e., they do not "do" anything until they are called --- they can be used to define control structures. For example, all Smalltalk's standard control structures, including branches (if/then/else) and loops (while and for), are defined using objects whose methods accept closures. Users can easily define their own control structures as well.
- Multiple functions can be produced which close over the same environment, enabling them to communicate privately by altering that environment.
Scheme was the first programming language to have fully general, lexically scoped closures. Virtually all functional programming languages, as well as the Smalltalk-descended object-oriented programming languages, support some form of closures. Some prominent languages that support closures include:
- Java allows the programmer to define "anonymous classeses" inside a method; an anonymous class may refer to names in lexically enclosing classes, or immutable names in the lexically enclosing method.
- In C++, programmers may define classes that overload the () (function application) operator. This enables instances of this class to behave syntactically like closures, although C++ provides no direct support for capturing names in the enclosing function's environment (the programmer can simulate some aspects of environment capture by using data members in the class). Instances of such classes are called function objects, or occasionally functors (although the latter term is confusing, because it has a very different meaning in other programming languages).
- funarg problem