I asked a question about Currying and closures were mentioned. What is a closure? How does it relate to currying?
相关问题
- Relation between Function1 and Reader Monad
- scala passing function with underscore produces a
- Combining n vectors into one vector of n-tuples
- Improve this code by eliminating nested for cycles
- Redefine list monad instance
相关文章
- Is there something like the threading macro from C
- Learning F#: What books using other programming la
- Creating a list of functions using a loop in R
- What does “exposition only” mean? Why use it?
- When to use interfaces, and when to use higher ord
- Functors in Ocaml
- Java Lambda Referencing Enclosing Object: Replace
- “Adapter” or “adaptor”?
tl;dr
A closure is a function and its scope assigned to (or used as) a variable. Thus, the name closure: the scope and the function is enclosed and used just like any other entity.
In depth Wikipedia style explanation
According to Wikipedia, a closure is:
What does that mean? Lets look into some definitions.
I will explain closures and other related definitions by using this example:
First-class functions
Basically that means we can use functions just like any other entity. We can modify them, pass them as arguments, return them from functions or assign them for variables. Technically speaking, they are first-class citizens, hence the name: first-class functions.
In the example above,
startAt
returns an (anonymous) function which function get assigned toclosure1
andclosure2
. So as you see JavaScript treats functions just like any other entities (first-class citizens).Name binding
Name binding is about finding out what data a variable (identifier) references. The scope is really important here, as that is the thing that will determine how a binding is resolved.
In the example above:
y
is bound to3
.startAt
's scope,x
is bound to1
or5
(depending on the closure).Inside the anonymous function's scope,
x
is not bound to any value, so it needs to be resolved in an upper (startAt
's) scope.Lexical scoping
As Wikipedia says, the scope:
There are two techniques:
For more explanation, check out this question and take a look at Wikipedia.
In the example above, we can see that JavaScript is lexically scoped, because when
x
is resolved, the binding is searched in the upper (startAt
's) scope, based on the source code (the anonymous function that looks for x is defined insidestartAt
) and not based on the call stack, the way (the scope where) the function was called.Wrapping (closuring) up
In our example, when we call
startAt
, it will return a (first-class) function that will be assigned toclosure1
andclosure2
thus a closure is created, because the passed variables1
and5
will be saved withinstartAt
's scope, that will be enclosed with the returned anonymous function. When we call this anonymous function viaclosure1
andclosure2
with the same argument (3
), the value ofy
will be found immediately (as that is the parameter of that function), butx
is not bound in the scope of the anonymous function, so the resolution continues in the (lexically) upper function scope (that was saved in the closure) wherex
is found to be bound to either1
or5
. Now we know everything for the summation so the result can be returned, then printed.Now you should understand closures and how they behave, which is a fundamental part of JavaScript.
Currying
Oh, and you also learned what currying is about: you use functions (closures) to pass each argument of an operation instead of using one functions with multiple parameters.
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:
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:
it is an open expression because there are symbols in it which has not been defined in it. Namely,
y
. When looking at this function, we can't tell whaty
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 whaty
is supposed to mean in it. Thisy
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 :PFor example, it could be defined globally:
Or it could be defined in a function which wraps it:
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: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: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 that it actually is.
Closures Whenever we have a function defined inside another function, the inner function has access to the variables declared in the outer function. Closures are best explained with examples. In Listing 2-18, you can see that the inner function has access to a variable (variableInOuterFunction) from the outer scope. The variables in the outer function have been closed by (or bound in) the inner function. Hence the term closure. The concept in itself is simple enough and fairly intuitive.
source: http://index-of.es/Varios/Basarat%20Ali%20Syed%20(auth.)-Beginning%20Node.js-Apress%20(2014).pdf
I'll give an example (in JavaScript):
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:
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.
A closure is a function that can reference state in another function. For example, in Python, this uses the closure "inner":
Functions containing no free variables are called pure functions.
Functions containing one or more free variables are called closures.
src: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure