Lexical Closure

A Lexical Closure, often referred to just as a closure, is a function that can refer to and alter the values of bindings established by binding forms that textually include the function definition.

By 'binding', we mean the association of a name with a value. By 'binding forms', we mean the constructs that define bindings and their scope in the language.

Consider the following example in Common Lisp:

(defun two-funs (x) (list (function (lambda () x)) (function (lambda (y) (setq x y))))) (setq funs1 (two-funs 6)) (funcall (first funs1)) => 6 (funcall (second funs1) 43) => 43 (funcall (first funs1)) => 43 (setq funs2 (two-funs 5)) (funcall (first funs2)) => 5 (funcall (second funs2) 13) => 13 (funcall (first funs2)) => 13 (funcall (first funs1)) => 43

Each time TWO-FUNS is called, each lambda expression is evaluated to produce a closure. The two closures are returned as a list of two elements. A different lexical environment is in effect each time, in which the name X is bound to a value. The two closures share the binding of X. However, each call to TWO-FUNS results in a new lexical environment, so that the binding of X used by the closures in FUNS1 is distinct from the bindings of X used by the closures in FUNS2.

In languages or situations in which the bindings are immutable, a closure acts as if the references to lexical bindings had been replaced by their values when the closure is created. However, as the example illustrates, the bindings can be changed in languages that have mutable variables.

The concept of lexical closure is potentially relevant to any programming language that supports lexical binding scopes and the definition of functions within a resulting lexical environment.

Lexical closures are most interesting in, and are usually associated with, languages that can treat functions as data (First Class Functions), since storing a closure for later use implies an extension of the lifetime of the closed-over lexical environment beyond what one would normally expect. However, there are languages without first-class functions that allow for the definition of functions in lexical scopes (e.g. Pascal, Algol). These nested functions can be used only within that lexical scope, and thus the lifetime of lexical bindings are not extended in such languages. Although 'closures' in such languages are far less powerful as a way of organizing program, they still serve as a useful notational convenience.

Languages that support lexical closures include:

Cee Sharp (version 2.0+)

Php Language (version 5.3+)

Python Language (full support since version 3 by nonlocal-declaration; partial support before, see web.archive.org )

Pascal Language (no first-class functions)

Algol Language (no first-class functions)

Objective Cee (version 2.1+; available for Mac OS X 10.6+)

Cee Language and Cee Plus Plus (with the open source Clang(Cee Language Family Front End)/LLVM (Low Level Virtual Machine) compiler; Apple has submitted the specification for consideration by the ANSI C Standards Committee)

C++11 (Cee Plus Plus Eleven) (Partial support with new C++ lambdas--the programmer chooses whether the lambda makes copies of the captured stack variables or only references them. References will cause Undefined Behavior if the lambda escapes the scope it was created in.

In Pascal Language and Algol Language, a function can be passed as an argument to another function, but cannot be stored in a variable or data structure, cannot be returned from a function, and cannot be created without being given a name. However, when a function is passed to another function and later called, it will execute in the lexical context it was defined in, so it is, in some sense, "closed over" that context.


Notes on the above definition:

I rewrote the definition that was here, because it was not as clear as it could have been regarding the mutability of bindings. The wikipedia entry for closures suffers from the same problem. I was recently involved in an online discussion with someone who had misunderstood this, and it appears that some of the developers working on C# at Microsoft may have, also. See blogs.msdn.com . Thus they seem to think that the anonymous methods in C# version 2.0 somehow differ from lexical closures.

The definition and example that I have given are adapted from the the Common Lisp standard specification; cf. www.lisp.org . It is my contention that in a language supporting mutable bindings (variables), a lexical closure must support mutability of the closed-over bindings. I tried to modify and expand the definition to make it language agnostic.

The original definition follows. Delete When Cooked. Note that the reference to SICP is misleading; as far as I can tell, SICP does not refer to lexical closures by that name, although it may describe the concepts involved. Also, AFAICT, the Scheme standard document does not mention closures by name either.

I also tried to succinctly address some issues that were discussed later on this page. For instance, the last paragraph should make it clear that dynamic typing is not relevant to the definition of a lexical closure.

In response to someone's addition of Pascal and Algol to the language list, I added a paragraph about 'closures' in languages lacking first-class functions.

Someone else clarified that functions can be passed as parameters in Pascal and Algol. I didn't remember this feature (haven't used Pascal in many years, and never learned Algol). Thanks!


Previous definition appearing on this page:

A Lexical Closure is a function whose Free Variables have been given values by an enclosing Lexical Scope.

Lexical closures are typically (but not always) formed by defining a function inside another function, for example (in Scheme Language):

(define (foo x) (define (bar y) (+ x y)) bar)

Now calling (foo arg) returns a closure consisting of a) the code of 'bar', and b) an environment where x has the value of arg.

(define bar1 (foo 1)) (define bar2 (foo 2))

(bar1 5) => 6 (bar2 5) => 7

In proper closures, not just the value is kept, but a reference to the actual object passed in. See the body of this page for a full explanation. As you may have noticed, lexical closures are necessary for Currying Schonfinkelling.

Those who are really interested in this should read Structure And Interpretation Of Computer Programs.


Objective Caml example, where an enclosing 'let' is used rather than an enlcosing function:

let produce_counter_from initval = let value = ref initval in fun () -> incr value; (!value, initval);;

let mycount = produce_counter_from 3;; mycount ();; (* produces (4, 3) *) mycount ();; (* produces (5, 3) *)

The anonymous function defined by 'fun () -> ...' remembers the names value and initval, which are bound in the surrounding scopes defined by the two 'let's. These names are accessible to it even after the call to produce_counter_from has finished.


Note that although Anonymous Functions are often used to create closures, they are not necessary. Named Functions work equally well.


A lexical closure is called just like an ordinary function. When this happens, the code of the closure is executed, and the references to the 'captured' Lexical Variables just work. For this, the captured lexicals must be saved somehow, in an object that persists as long as the closure exists. This means the lexical variables can't be stored in an ordinary stack frame that expires when the execution of the outer Lexical Scope is finished.

The closure has internal variables too, such as the parameters of its anonymous function, or local variables defined within the body of that function. These are the closure's bound variables, and are not included in the closure object, because their bindings are established whenever the closure is called. The captured variables from the surrounding environments are called free variables (that is, free with respect to the function because they are not bound within it but have to be "reached" for in the lexical environment). It's useful to know this free variable terminology because it's somewhat counter-intuitive, yet used quite a bit in the literature.

A Common Lisp example is useful, because the syntax is fairly obvious even to non-Lisp programmers, thanks to the parentheses that denote the tree structure without ambiguity.

(defun make-counter (initial-value) ; initial-value is the variable we will capture in our anonymous function (lambda () ; We'll make a closure that takes no parameters (incf initial-value)))) ; This is equivalent to '++initial-value' in C

The result of the 'lambda' expression (a closure) is returned as the result of 'make-counter'.

(defvar *closure-one* (make-counter 10)) (defvar *closure-two* (make-counter 100))

(funcall *closure-one*) ;; --> 11 (funcall *closure-two*) ;; --> 101 (funcall *closure-one*) ;; --> 12 (funcall *closure-one*) ;; --> 13 (funcall *closure-two*) ;; --> 102

As you can see, two closure objects were made, each capturing a distinct binding of the INITIAL-VALUE variable, giving rise to two independent counting sessions. Note how the closures can continue to access INITIAL-VALUE, even though it's the parameter of a function call that has terminated.


Here is a similar example from Scheme Language. The goal is to create a counter.

(define (make-counter) (let ((count 0)) (lambda () (set! count (+ count 1)) count)))

What does this do? Well, every time you call (make-counter), it produces a new counter procedure, like so:

(define counter1 (make-counter))

Now repeated calls to (counter1) will produce 1, 2, 3, etc... What happens is that the variable count (which is a local variable to the procedure make-counter) remains accessible by the counter procedure even after make-counter has terminated.

---

And here's the same program in C# 2.0:

static Function<int> makeCounter() { int count = 0; return delegate() { return ++count; } }

Function<int> counter1 = makeCounter(); Function<int> counter2 = makeCounter(); Console.Write''''''Line(counter1()) // prints 1 Console.Write''''''Line(counter1()) // prints 2 Console.Write''''''Line(counter2()) // prints 1

--- Some may ask: what are closures for? For a typical example, compare the pain some languages have in getting a callback to occur. You register some specific function, or functor object, worry about who destroys it, etc. In Common Lisp, you register a Lexical Closure which closes over all the relevant state and objects, and the callback occurs when the other thread funcalls the closure. Problem solved---no fuss, no muss. Yet another [one of the Benefits Of Dynamic Typing]. --Alain Picard


The preceding comment that closures are a benefit of dynamic typing seems to be incorrect. Take the first example on this page: it is written in Objective Caml, which is a statically-typed language.

Lexical Closures are clearly not a benefit of Dynamic Typing, or even of Implicit Typing, since it is possible to have closures without implicit or dynamic typing, and implicit or dynamic typing without closures.

But like many other programming language features, they form a Cross Product with Implicit Typing, which enhances their utility. In a implicitly typed setting, like that of either Common Lisp or Objective Caml, a call to a function is correct if it merely gets the syntax right: all the required parameters are present, keyword parameters are paired up properly with the indicators and so on. There is no requirement (although it may be possible) to statically declare some function to have a given parameter type signature. If some subsystem of a program wants a one-argument callback, any old one-argument function will do, provided it doesn't try to misuse the object it is given. This means that you are not forced into writing dummy functions just for the sake of adapting to some manifestly typed interface so that your program compiles. It also means that if you are writing macros, your job is substantially easier, because you don't have to extract type information from the macro parameters in order to construct the right kind of closure.

In implicitly typed languages with Type Inference (ML and friends, Haskell, etc.), there is the added guarantee that calling a closure won't fall over at runtime with a type mismatch error.


Closures are not the same as generators (Generator Closure), but they are closely related. Generators are a very easily implemented with closures, and a generator can be thought of a as a very limited kind of closure.



See original on c2.com