Closure (computer programming): Difference between revisions

Content deleted Content added
No edit summary
Tags: Reverted nowiki added references removed Visual edit Mobile edit Mobile web edit
Bender the Bot (talk | contribs)
m External links: HTTP to HTTPS for Blogspot
 
(11 intermediate revisions by 9 users not shown)
Line 3:
{{Distinguish|text=the programming language [[Clojure]]}}
{{Use dmy dates|date=August 2020}}
In [[programming language]]s, a '''closure''', also '''lexical closure''' or '''function closure''', is meant a functiontechnique alongfor withimplementing a[[lexically setscoped]] of[[name valuesbinding]] associatedin a language with its[[first-class parametersfunction]]s. [[Operational semantics|Operationally]], a closure is a [[Record (computer science)|record]] storing a [[Function (computer science)|function]]{{efn|The function may be stored as a [[Reference (computer science)|reference]] to a function, such as a [[function pointer]].}} together with itsan contextenvironment.<ref>Sussman and Steele. "Scheme: An interpreter for extended lambda calculus". "... a data structure containing a lambda expression, and an environment to be used when that lambda expression is applied to arguments." (i[[s:Page:Scheme - An interpreter for extended lambda calculus.edjvu/22|Wikisource]])</ref> The environment is a mapping associating each [[free variable]] of the function (variables that are used locally, but defined in an enclosing scope) with the [[Value (computer science)|value]] or [[Reference (computer science)|reference]] to which the name was bound when the closure was created.{{efn|These names usually refer to values, mutable variables, or functions, but can also be other entities such as constants, types, classes, or labels.}} Unlike a plain function, a closure allows the function to access those ''captured variables'' through the closure's copies of their values or references, even when the function is invoked outside their scope.
 
== History and etymology ==
The concept of closures wasinwas developed in the 1960s for the mechanical evaluation of expressions in the [[λ-calculus|λ-calcul(us]] and was f)iforfirst eachfully ofimplemented itain parameters.1970 Aas clsupporta lexicaoycatchlanguage the environmentfeature in which a scopedthe [[first-class function|f]]<nowiki/>is called, regardless the invocation scopePAL (as,programming bringinglanguage)|PAL theprogramming contextlanguage]] along,to thesupport invocationlexically isscoped thus self[[first-contained,class i.e. ''closed'')function]]s.<ref name=dat2012>{{cite conference |author-link=David A. Turner |first=David A. |last=Turner |year=2012 |url=http://www.cs.kent.ac.uk/people/staff/dat/tfp12/tfp12.pdf |title=Some History of Functional Programming Languages |book-title=International Symposium on Trends in Functional Programming |pages=1–20 See 12 §2, note 8 for the claim about M-expressions |publisher=Springer |doi=10.1007/978-3-642-40447-4_1 |isbn=978-3-642-40447-4 |series=Lecture Notes in Computer Science |volume=7829}}</ref>
 
[[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 SIGSAM 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 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 604:
|date=2007-01-28
|title=A Definition of Closures
|url=httphttps://gafter.blogspot.com/2007/01/definition-of-closures.html
}}
* {{cite web