A closure is a programming concept that combines a function with the context in which it was created so that the function retains access to the variables that were in scope at its creation. In computer science this is an important mechanism for implementing callbacks, data encapsulation, and higher-order functions. The key idea is that the function carries an implicit association to an environment — a mapping of names to values — and that this environment persists even after the outer routine that created it has finished executing.
Definition and characteristics
At minimum, a closure consists of three parts: the code of the function, the set of referenced variables that were bound when the function was created, and the reference to that bound environment. Because of this capture of bindings, closures can read and often update the values of those variables across multiple invocations. Closures are closely tied to lexical (static) scoping: the variables captured are those visible by name at the function's point of definition, not where it is called.
How closures work
- Creation: a closure is formed when a function is defined inside another function and it refers to outer variables.
- Capture: the outer variables referenced become part of the closure's environment and are preserved.
- Lifetime: the preserved environment remains alive as long as the closure can be reached, preventing its variables from being reclaimed.
History and language support
The term "closure" was introduced in the 1960s; early work on functional languages clarified the concept. Peter J. Landin helped popularize the term, and subsequent languages solidified its role. The dialect Scheme highlighted closures in the 1970s, and many modern programming languages adopted them. Today closures appear in functional and multi-paradigm languages because they enable concise expression of stateful behavior without relying on global variables or explicit objects.
Uses and examples
Closures support common programming patterns: creating factory functions that remember configuration, implementing iterators or generators that preserve iteration state, writing event handlers and callbacks that carry context, and encapsulating private state without exposing it as a public variable. They are often used with anonymous functions — unnamed function literals — but a function must also capture an environment to be a true closure.
Common misconceptions and distinctions
Not every function value is a closure. A function value becomes a closure only when it carries its defining environment with it. Sometimes anonymous functions are called closures loosely; the stricter meaning requires at least one captured binding. A ‘‘named closure’’ is simply a function with a retained environment that also has an identifier. Implementations and performance characteristics vary across languages: some realize closures with heap-allocated activation records, others with specialized runtime support.
Understanding closures helps programmers reason about scope, lifetime, and privacy of data and is central to modern functional programming and many practical coding patterns.