Every now and then I see "closures" being mentioned, and I tried looking it up but Wiki doesn't give an explanation that I understand. Could someone help me out here?
- Anybody can ask a question
- Anybody can answer
- The best answers are voted up and rise to the top
(Disclaimer: this is a basic explanation; as far as the definition goes, I'm simplifying a little bit)
The most simple way to think of a closure is a function that can be stored as a variable (referred to as a "first-class function"), that has a special ability to access other variables local to the scope it was created in.
The functions1 assigned to
If you put this in an HTML page:
This demonstrates that both have access to the same
The call to
A closure is basically just a different way of looking at an object. An object is data that has one or more functions bound to it. A closure is a function that has one or more variables bound to it. The two are basically identical, at an implementation level at least. The real difference is in where they come from.
In object-oriented programming, you declare an object class by defining its member variables and its methods (member functions) up-front, and then you create instances of that class. Each instance comes with a copy of the member data, initialized by the constructor. You then have a variable of an object type, and pass it around as a piece of data, because the focus is on its nature as data.
In a closure, on the other hand, the object is not defined up-front like an object class, or instantiated through a constructor call in your code. Instead, you write the closure as a function inside of another function. The closure can refer to any of the outer function's local variables, and the compiler detects that and moves these variables from the outer function's stack space to the closure's hidden object declaration. You then have a variable of a closure type, and even though it's basically an object under the hood, you pass it around as a function reference, because the focus is on its nature as a function.
The term closure comes from the fact that a piece of code (block, function) can have free variables that are closed (i.e. bound to a value) by the environment in which the block of code is defined.
Take for example the Scala function definition:
In the function body there are two names (variables)
In order to evaluate a call like:
we have to assign
Now that we have defined
So a closure is basically a function or code block that can access non-local values through its free variables after these have been bound by the context.
In many languages, if you use a closure only once you can make it anonymous, e.g.
Note that a function with no free variables is a special case of a closure (with an empty set of free variables). Analogously, an anonymous function is a special case of an anonymous closure, i.e. an anonymous function is an anonymous closure with no free variables.
If you run this code, the first iteration will assign a value 0 to the
And now every time you call the
A "closure" is, in essence, some local state and some code, combined into a package. Typically, the local state comes from a surrounding (lexical) scope and the code is (essentially) an inner function that is then returned to outside. The closure is then a combination of the captured variables that the inner function sees and the code of the inner function.
It's one of those things that is, unfortunately, a bit hard to explain, due to being unfamiliar.
One analogy I successfully used in the past was "imagine we have something we call 'the book', in the room-closure, 'the book' is that copy there, over in the corner, of TAOCP, but on the table-closure, it's that copy of a Dresden Files book. So depending on what closure you're in, the code 'give me the book' results in different things happening."
It is hard to define what closure is without defining the concept of 'state'.
Basically, in a language with full lexical scoping that treats functions as first class values, something special happens. If I were to do something like:
Functionally it can solve many of the same problems as the C++(C?)'s 'static' keyword, which retains a local variable's state throughout multiple function calls; however it's more like applying that same principle (static variable) to a function, as functions are first class values; closure adds support for the entire function's state to be saved (nothing to do with C++'s static functions).
Treating functions as first class values and adding support for closures also means that you can have more than one instance of the same function in memory (similar to classes). What this means is you can re-use the same code without having to reset the function's state, as is required when dealing with C++ static variables inside a function(may be wrong about this?).
Here is some testing of Lua's closure support.
It can get tricky, and it probably varies from language to language, but it seems in Lua that whenever a function is executed, its state is reset. I say this because the results from the code above would be different if we were accessing the
PS: I don't know a lick of C++11 (other than what's in previous versions) so do note that this isn't a comparison between closures in C++11 and Lua. Also, all the 'lines drawn' from Lua to C++ are similarities as static variables and closures are not 100% the same; even if they are sometimes used to solve similar problems.
The thing I'm not sure of is, in the code example above, whether the anonymous function or the higher order function is considered the closure?
A closure is a function that has associated state:
In perl you create closures like this:
If we look at the new functionality provided with C++.
Let's consider a simple function:
In top-level functions, the scope chain consists of a single object, the global object. For example, the function
So, we now know this:
The situation gets interesting when we deal with nested functions. So, let's create one:
If there were another nested function defined within
So, now we understand how scope chain works but we haven't talked about closures yet.
Most functions are invoked using the same scope chain that was in effect when the function was defined, and it doesn’t really matter that there is a closure involved. Closures become interesting when they are invoked under a different scope chain than the one that was in effect when they were defined. This happens most commonly when a nested function object is returned from the function within which it was defined.
When the function returns, that activation object is removed from the scope chain. If there were no nested functions, there are no more references to the activation object and it gets garbage collected. If there were nested functions defined, then each of those functions has a reference to the scope chain, and that scope chain refers to the activation object.
If those nested functions objects remained within their outer function, however, then they themselves will be garbage collected, along with the activation object they referred to. But if the function defines a nested function and returns it or stores it into a property somewhere, then there will be an external reference to the nested function. It won’t be garbage collected, and the activation object it refers to won’t be garbage collected either.
In our above example, we don't return
Here, the returning
There are a number of powerful programming techniques that involve closures like approximating private variables, event driven programming, partial application, etc.
Also note that all of this applies to all those languages that support closures. For example PHP (5.3+), Python, Ruby, etc.
A closure is a compiler optimization (aka syntactic sugar?). Some people have referred to this as the Poor Man's Object as well.
See the answer by Eric Lippert : (excerpt below)
The compiler will generate code like this:
protected by MichaelT Jun 15 '15 at 18:13
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?