Closure (computer programming): Difference between revisions

Content deleted Content added
Bender the Bot (talk | contribs)
m External links: HTTP to HTTPS for Blogspot
 
(15 intermediate revisions by 12 users not shown)
Line 10:
[[Peter Landin]] defined the term ''closure'' in 1964 as having an ''environment part'' and a ''control part'' as used by his [[SECD machine]] for evaluating expressions.<ref name=landin>
{{cite journal |last=Landin |first=P.J. |author-link=Peter Landin |title=The mechanical evaluation of expressions |journal=The Computer Journal |volume=6 |issue=4 |date=January 1964 |pages=308–320 |doi=10.1093/comjnl/6.4.308 |url=https://academic.oup.com/comjnl/article-pdf/6/4/308/1067901/6-4-308.pdf }}</ref> [[Joel Moses]] credits Landin with introducing the term ''closure'' to refer to a [[Anonymous function|lambda expression]] with open bindings (free variables) that have been closed by (or bound in) the lexical environment, resulting in a ''closed expression'', or closure.<ref>
{{cite journal |last=Moses |first=Joel |author-link=Joel Moses |date=June 1970 |title=The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem |journal=ACM SigsamSIGSAM Bulletin |issue=15 |pages=13–27 |doi=10.1145/1093410.1093411 |id=[[AI Memo]] 199 |quote=A useful metaphor for the difference between FUNCTION and QUOTE in LISP is to think of QUOTE as a porous or an open covering of the function since free variables escape to the current environment. FUNCTION acts as a closed or nonporous covering (hence the term "closure" used by Landin). Thus we talk of "open" Lambda expressions (functions in LISP are usually Lambda expressions) and "closed" Lambda expressions. [...] My interest in the environment problem began while Landin, who had a deep understanding of the problem, visited MIT during 1966–67. I then realized the correspondence between the FUNARG lists which are the results of the evaluation of "closed" Lambda expressions in [[LISP 1.5|LISP]] and [[ISWIM]]'s Lambda Closures.|hdl=1721.1/5854|s2cid=17514262 |hdl-access=free }}</ref><ref>{{cite book |last=Wikström |first=Åke |year=1987 |title=Functional Programming using Standard ML |publisher=Prentice Hall |isbn=0-13-331968-7 |quote=The reason it is called a "closure" is that an expression containing free variables is called an "open" expression, and by associating to it the bindings of its free variables, you close it.}}</ref> This use was subsequently adopted by [[Gerald Jay Sussman|Sussman]] and [[Guy L. Steele Jr.|Steele]] when they defined [[Scheme (programming language)|Scheme]] in 1975,<ref>{{cite report |last1=Sussman |first1=Gerald Jay |author1-link=Gerald Jay Sussman |last2=Steele |first2=Guy L. Jr. |author2-link=Guy L. Steele Jr. |date=December 1975 |title=Scheme: An Interpreter for the Extended Lambda Calculus |id=[[AI Memo]] 349}}</ref> a lexically scoped variant of [[Lisp (programming language)|Lisp]], and became widespread.
 
Sussman and [[Harold Abelson|Abelson]] also use the term ''closure'' in the 1980s with a second, unrelated meaning: the property of an operator that adds data to a [[data structure]] to also be able to add nested data structures. This use of the term comes from [[Closure (mathematics)|mathematics use]], rather than the prior use in computer science. The authors consider this overlap in terminology to be "unfortunate."<ref>{{cite book |last1=Abelson |first1=Harold |author1-link=Harold Abelson |last2=Sussman |first2=Gerald Jay |author2-link=Gerald Jay Sussman |last3=Sussman |first3=Julie |author3-link=Julie Sussman |date=1996 |title=Structure and Interpretation of Computer Programs |url=https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html |publisher=MIT Press |pages=98–99 |isbn=0-262-51087-1}}</ref>
Line 46:
The nested function definitions are not themselves closures: they have a free variable which is not yet bound. Only once the enclosing function is evaluated with a value for the parameter is the free variable of the nested function bound, creating a closure, which is then returned from the enclosing function.
 
Lastly, a closure is only distinct from a function with free variables when outside of the scope of the non-local variables, otherwise the defining environment and the execution environment coincide and there is nothing to distinguish these (static and dynamic binding cannot be distinguished because the names resolve to the same values). For example, in the below program below, functions with a free variable <code>x</code> (bound to the non-local variable <code>x</code> with global scope) are executed in the same environment where <code>x</code> is defined, so it is immaterial whether these are actually closures:
<syntaxhighlight lang="python">
x = 1
Line 59:
This is most often achieved by a function return, since the function must be defined within the scope of the non-local variables, in which case typically its own scope will be smaller.
 
This can also be achieved by [[variable shadowing]] (which reduces the scope of the [[non-local variable]]), though this is less common in practice, as it is less useful and shadowing is discouraged. In this example <code>f</code> can be seen to be a closure because <code>x</code> in the body of <code>f</code> is bound to the <code>x</code> in the global namespace, not the <code>x</code> local to <code>g</code>:
<syntaxhighlight lang="python">
x = 0
Line 102:
</syntaxhighlight>
 
The arrow operator <code>=></code> is used to define an [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow%20functionsArrow_functions arrow function expression], and an <code>Array.filter</code> method<ref>{{cite web |url=https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter |title=array.filter |work=Mozilla Developer Center |date=10 January 2010 |access-date=2010-02-09}}</ref> instead of a global <code>filter</code> function, but otherwise the structure and the effect of the code are the same.
 
A function may create a closure and return it, as in this example:
Line 203:
 
===Example 2: Accidental reference to a bound variable===
For this example the expected behaviour would be that each link should emit its id when clicked; but because the variable 'e' is bound to the scope above, and lazy evaluated on click, what actually happens is that each on click event emits the id of the last element in 'elements' bound at the end of the [[for loop]].<ref>{{cite web |title=Closures |url=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops_A_common_mistake |website=MDN Web Docs |access-date=20 November 2018}}</ref>
<syntaxhighlight lang="javascript">
var elements = document.getElementsByTagName('a');
Line 541:
 
=== Function objects (C++) ===
[[C++]] enables defining [[function object]]s by overloading <code>operator()</code>. These objects behave somewhat like functions in a functional programming language. They may be created at runtime and may contain state, but they do not implicitly capture local variables as closures do. As of [[C++11|the 2011 revision]], the C++ language also supports closures, which are a type of function object constructed automatically from a special [[language construct]] called ''lambda-expression''. A C++ closure may capture its context either by storing copies of the accessed variables as members of the closure object or by reference. In the latter case, if the closure object escapes the scope of a referenced object, invoking its <code>operator()</code> causes undefined behavior since C++ closures do not extend the lifetime of their context.{{main|Anonymous functionExamples_of_anonymous_functions#C++ _(since Csince_C++11)}}
 
<syntaxhighlight lang="cpp">
Line 583:
 
== See also ==
{{div col}}
* [[Command pattern]]
* [[Currying]]
Line 589 ⟶ 590:
* [[Syntactic closure]]
* [[Value-level programming]]
{{div col end}}
 
== Notes ==
Line 602 ⟶ 604:
|date=2007-01-28
|title=A Definition of Closures
|url=httphttps://gafter.blogspot.com/2007/01/definition-of-closures.html
}}
* {{cite web