Definition of closure 1 : an act of closing : the condition of being closed closure of the eyelids business closures the closure of the factory. 2 : an often comforting or satisfying sense of finality victims needing closure also : something (such as a satisfying ending) that provides such a sense.
Definitions of law of closure. a Gestalt principle of organization holding that there is an innate tendency to perceive incomplete objects as complete and to close or fill gaps and to perceive asymmetric stimuli as symmetric.
A closure is a programming technique that allows variables outside of the scope of a function to be accessed. Usually, a closure is created when a function is defined in another function, allowing the inner function to access variables in the outer one.
: a meeting or a portion of a meeting closed to all but members The board will meet in closed session to discuss the issue.
When you declare a local variable, that variable has a scope. Generally, local variables exist only within the block or function in which you declare them.
function() {
var a = 1;
console.log(a); // works
}
console.log(a); // fails
If I try to access a local variable, most languages will look for it in the current scope, then up through the parent scopes until they reach the root scope.
var a = 1;
function() {
console.log(a); // works
}
console.log(a); // works
When a block or function is done with, its local variables are no longer needed and are usually blown out of memory.
This is how we normally expect things to work.
A closure is a persistent scope which holds on to local variables even after the code execution has moved out of that block. Languages which support closure (such as JavaScript, Swift, and Ruby) will allow you to keep a reference to a scope (including its parent scopes), even after the block in which those variables were declared has finished executing, provided you keep a reference to that block or function somewhere.
The scope object and all its local variables are tied to the function and will persist as long as that function persists.
This gives us function portability. We can expect any variables that were in scope when the function was first defined to still be in scope when we later call the function, even if we call the function in a completely different context.
Here's a really simple example in JavaScript that illustrates the point:
outer = function() {
var a = 1;
var inner = function() {
console.log(a);
}
return inner; // this returns a function
}
var fnc = outer(); // execute outer to get inner
fnc();
Here I have defined a function within a function. The inner function gains access to all the outer function's local variables, including a
. The variable a
is in scope for the inner function.
Normally when a function exits, all its local variables are blown away. However, if we return the inner function and assign it to a variable fnc
so that it persists after outer
has exited, all of the variables that were in scope when inner
was defined also persist. The variable a
has been closed over -- it is within a closure.
Note that the variable a
is totally private to fnc
. This is a way of creating private variables in a functional programming language such as JavaScript.
As you might be able to guess, when I call fnc()
it prints the value of a
, which is "1".
In a language without closure, the variable a
would have been garbage collected and thrown away when the function outer
exited. Calling fnc would have thrown an error because a
no longer exists.
In JavaScript, the variable a
persists because the variable scope is created when the function is first declared and persists for as long as the function continues to exist.
a
belongs to the scope of outer
. The scope of inner
has a parent pointer to the scope of outer
. fnc
is a variable which points to inner
. a
persists as long as fnc
persists. a
is within the closure.
I made a YouTube video looking at this code with some practical examples of usage.
I'll give an example (in JavaScript):
function makeCounter () {
var count = 0;
return function () {
count += 1;
return count;
}
}
var x = makeCounter();
x(); returns 1
x(); returns 2
...etc...
What this function, makeCounter, does is it returns a function, which we've called x, that will count up by one each time its called. Since we're not providing any parameters to x it must somehow remember the count. It knows where to find it based on what's called lexical scoping - it must look to the spot where it's defined to find the value. This "hidden" value is what is called a closure.
Here is my currying example again:
function add (a) {
return function (b) {
return a + b;
}
}
var add3 = add(3);
add3(4); returns 7
What you can see is that when you call add with the parameter a (which is 3), that value is contained in the closure of the returned function that we're defining to be add3. That way, when we call add3 it knows where to find the a value to perform the addition.
First of all, contrary to what most of the people here tell you, closure is not a function! So what is it?
It is a set of symbols defined in a function's "surrounding context" (known as its environment) which make it a CLOSED expression (that is, an expression in which every symbol is defined and has a value, so it can be evaluated).
For example, when you have a JavaScript function:
function closed(x) {
return x + 3;
}
it is a closed expression because all the symbols occurring in it are defined in it (their meanings are clear), so you can evaluate it. In other words, it is self-contained.
But if you have a function like this:
function open(x) {
return x*y + 3;
}
it is an open expression because there are symbols in it which have not been defined in it. Namely, y
. When looking at this function, we can't tell what y
is and what does it mean, we don't know its value, so we cannot evaluate this expression. I.e. we cannot call this function until we tell what y
is supposed to mean in it. This y
is called a free variable.
This y
begs for a definition, but this definition is not part of the function – it is defined somewhere else, in its "surrounding context" (also known as the environment). At least that's what we hope for :P
For example, it could be defined globally:
var y = 7;
function open(x) {
return x*y + 3;
}
Or it could be defined in a function which wraps it:
var global = 2;
function wrapper(y) {
var w = "unused";
return function(x) {
return x*y + 3;
}
}
The part of the environment which gives the free variables in an expression their meanings, is the closure. It is called this way, because it turns an open expression into a closed one, by supplying these missing definitions for all of its free variables, so that we could evaluate it.
In the example above, the inner function (which we didn't give a name because we didn't need it) is an open expression because the variable y
in it is free – its definition is outside the function, in the function which wraps it. The environment for that anonymous function is the set of variables:
{
global: 2,
w: "unused",
y: [whatever has been passed to that wrapper function as its parameter `y`]
}
Now, the closure is that part of this environment which closes the inner function by supplying the definitions for all its free variables. In our case, the only free variable in the inner function was y
, so the closure of that function is this subset of its environment:
{
y: [whatever has been passed to that wrapper function as its parameter `y`]
}
The other two symbols defined in the environment are not part of the closure of that function, because it doesn't require them to run. They are not needed to close it.
More on the theory behind that here: https://stackoverflow.com/a/36878651/434562
It's worth to note that in the example above, the wrapper function returns its inner function as a value. The moment we call this function can be remote in time from the moment the function has been defined (or created). In particular, its wrapping function is no longer running, and its parameters which has been on the call stack are no longer there :P This makes a problem, because the inner function needs y
to be there when it is called! In other words, it requires the variables from its closure to somehow outlive the wrapper function and be there when needed. Therefore, the inner function has to make a snapshot of these variables which make its closure and store them somewhere safe for later use. (Somewhere outside the call stack.)
And this is why people often confuse the term closure to be that special type of function which can do such snapshots of the external variables they use, or the data structure used to store these variables for later. But I hope you understand now that they are not the closure itself – they're just ways to implement closures in a programming language, or language mechanisms which allows the variables from the function's closure to be there when needed. There's a lot of misconceptions around closures which (unnecessarily) make this subject much more confusing and complicated than it actually is.
Kyle's answer is pretty good. I think the only additional clarification is that the closure is basically a snapshot of the stack at the point that the lambda function is created. Then when the function is re-executed the stack is restored to that state before executing the function. Thus as Kyle mentions, that hidden value (count
) is available when the lambda function executes.
A closure is a function that can reference state in another function. For example, in Python, this uses the closure "inner":
def outer (a):
b = "variable in outer()"
def inner (c):
print a, b, c
return inner
# Now the return value from outer() can be saved for later
func = outer ("test")
func (1) # prints "test variable in outer() 1
To help facilitate understanding of closures it might be useful to examine how they might be implemented in a procedural language. This explanation will follow a simplistic implementation of closures in Scheme.
To start, I must introduce the concept of a namespace. When you enter a command into a Scheme interpreter, it must evaluate the various symbols in the expression and obtain their value. Example:
(define x 3)
(define y 4)
(+ x y) returns 7
The define expressions store the value 3 in the spot for x and the value 4 in the spot for y. Then when we call (+ x y), the interpreter looks up the values in the namespace and is able to perform the operation and return 7.
However, in Scheme there are expressions that allow you to temporarily override the value of a symbol. Here's an example:
(define x 3)
(define y 4)
(let ((x 5))
(+ x y)) returns 9
x returns 3
What the let keyword does is introduces a new namespace with x as the value 5. You will notice that it's still able to see that y is 4, making the sum returned to be 9. You can also see that once the expression has ended x is back to being 3. In this sense, x has been temporarily masked by the local value.
Procedural and object-oriented languages have a similar concept. Whenever you declare a variable in a function that has the same name as a global variable you get the same effect.
How would we implement this? A simple way is with a linked list - the head contains the new value and the tail contains the old namespace. When you need to look up a symbol, you start at the head and work your way down the tail.
Now let's skip to the implementation of first-class functions for the moment. More or less, a function is a set of instructions to execute when the function is called culminating in the return value. When we read in a function, we can store these instructions behind the scenes and run them when the function is called.
(define x 3)
(define (plus-x y)
(+ x y))
(let ((x 5))
(plus-x 4)) returns ?
We define x to be 3 and plus-x to be its parameter, y, plus the value of x. Finally we call plus-x in an environment where x has been masked by a new x, this one valued 5. If we merely store the operation, (+ x y), for the function plus-x, since we're in the context of x being 5 the result returned would be 9. This is what's called dynamic scoping.
However, Scheme, Common Lisp, and many other languages have what's called lexical scoping - in addition to storing the operation (+ x y) we also store the namespace at that particular point. That way, when we're looking up the values we can see that x, in this context, is really 3. This is a closure.
(define x 3)
(define (plus-x y)
(+ x y))
(let ((x 5))
(plus-x 4)) returns 7
In summary, we can use a linked list to store the state of the namespace at the time of function definition, allowing us to access variables from enclosing scopes, as well as providing us the ability to locally mask a variable without affecting the rest of the program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With