Closure (computer programming): Difference between revisions

Content deleted Content added
Citation bot (talk | contribs)
Add: pages. Removed parameters. Some additions/deletions were parameter name changes. | Use this bot. Report bugs. | Suggested by Abductive | #UCB_webform 2470/3850
WP:REFerence WP:CITation parameters: updates, corrects, respaces, reorders, adds, fills, author > last + first, conform to master templates. Small WP:COPYEDITs WP:EoS: WP:TERSE, clarify, 2nd MOS:PERSON WP:YOUs fix-cut. WP:LINKs: adds, update-standardizes, needless WP:PIPEs > WP:NOPIPEs. MOS:FIRSTABBReviation clarify, define before WP:ABBR in parentheses. Cut needless carriage returns in: WP:CITations, paragraphs.
Line 1:
{{Short description|Technique for creating lexically scoped first class functions}}
{{otherOther uses|Closure (mathematics)|Closure (disambiguation)}}
{{distinguishDistinguish|text=the programming language [[Clojure]]}}
{{Use dmy dates|date=August 2020}}
In [[programming language]]s, a '''closure''', also '''lexical closure''' or '''function closure''', is a technique for implementing [[lexically scoped]] [[name binding]] in a language with [[first-class function]]s. [[Operational semantics|Operationally]], a closure is a [[recordRecord (computer science)|record]] storing a [[functionFunction (computer science)|function]]{{efn|The function may be stored as a [[referenceReference (computer science)|reference]] to a function, such as a [[function pointer]].}} together with an environment.<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." ([[s:Page:Scheme - An interpreter for extended lambda calculus.djvu/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 most frequently 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 was developed in the 1960s for the mechanical evaluation of expressions in the [[λ-calculus]] and was first fully implemented in 1970 as a language feature in the [[Rpal|PAL]] programming language to support lexically scoped [[first-class function]]s.<ref name=dat2012>[[David A. Turner]] (2012). [http://www.cs.kent.ac.uk/people/staff/dat/tfp12/tfp12.pdf "Some History of Functional Programming Languages"]. Trends in Functional Programming '12. Section 2, note 8 contains the claim about M-expressions.</ref>
 
[[Peter J. 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>{{citation
|{{cite authorreport |last=Landin |first=P. J. |author-link=Peter Landin | year = 1964 | title = The mechanical evaluation of expressions | author-link = Peter J. Landin }}</ref> [[Joel Moses]] credits Landin with introducing the term ''closure'' to refer to a [[Anonymous function|lambda expression]] whosewhich open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a ''closed expression'', or closure.<ref>{{citation
|{{cite authorreport |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 | 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 |author-link=Joel Moses }}</ref><ref>{{cite book |last=Wikström author |first= Åke Wikström| year =1987 1987| title = Functional Programming using Standard ML| |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.| author-link = Åke Wikström}}</ref> This usageuse was subsequently adopted by [[Gerald Jay Sussman|Sussman]] and [[Guy L. Steele, Jr.|Steele]] when they defined [[Scheme (programming language)|Scheme]] in 1975,<ref>{{citation|cite authorreport |last1=Sussman [[|first1=Gerald Jay |author1-link=Gerald Jay Sussman]] and|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 usageuse of the term comes from [[Closure (mathematics)|the mathematics usageuse]], rather than the prior usageuse 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 |___location=Cambridge, MA |publisher=MIT Press |pages=98–99 |isbn=0262510871}}</ref>
 
== Anonymous functions ==
Line 108:
</syntaxhighlight>
 
The <code>function</code> keyword is used here instead of <code>lambda</code>, 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 the followingthis example:
 
<syntaxhighlight lang="javascript">
Line 148:
</syntaxhighlight>
 
* Closures can be used to implement [[Object-oriented programming|object]] systems.<ref>{{cite web | url = http://okmij.org/ftp/Scheme/oop-in-fp.txt | title = Re: FP, OO and relations. Does anyone trump the others? | date = 29 December 1999 | access-date = 2008-12-23 | archive-url = https://web.archive.org/web/20081226055307/http://okmij.org/ftp/Scheme/oop-in-fp.txt | archive-date = 26 December 2008 | url-status = dead }}</ref>
 
Note: Some speakers call any data structure that binds a [[Scope (programming)#Lexical scoping|lexical]] environment a closure, but the term usually refers specifically to functions.
Line 222:
On the other hand, many functional languages, such as [[ML (programming language)|ML]], bind variables directly to values. In this case, since there is no way to change the value of the variable once it is bound, there is no need to share the state between closures—they just use the same values. This is often called capturing the variable "by value". Java's local and anonymous classes also fall into this category—they require captured local variables to be <code>final</code>, which also means there is no need to share state.
 
Some languages enable you to choosechoosing between capturing the value of a variable or its ___location. For example, in C++11, captured variables are either declared with <code>[&]</code>, which means captured by reference, or with <code>[=]</code>, which means captured by value.
 
Yet another subset, [[lazy evaluation|lazy]] functional languages such as [[Haskell (programming language)|Haskell]], bind variables to results of future computations rather than values. Consider this example in Haskell:
 
<syntaxhighlight lang="haskell">
Line 241:
 
=== Closure leaving ===
Yet more differences manifest themselves in the behavior of other lexically scoped constructs, such as <code>return</code>, <code>break</code> and <code>continue</code> statements. Such constructs can, in general, be considered in terms of invoking an [[escape continuation]] established by an enclosing control statement (in case of <code>break</code> and <code>continue</code>, such interpretation requires looping constructs to be considered in terms of recursive function calls). In some languages, such as ECMAScript, <code>return</code> refers to the continuation established by the closure lexically innermost with respect to the statement—thus, a <code>return</code> within a closure transfers control to the code that called it. However, in [[Smalltalk]], the superficially similar operator <code>^</code> invokes the escape continuation established for the method invocation, ignoring the escape continuations of any intervening nested closures. The escape continuation of a particular closure can only be invoked in Smalltalk implicitly by reaching the end of the closure's code. The followingThese examples in ECMAScript and Smalltalk highlight the difference:
 
<syntaxhighlight lang="smalltalk">
Line 355:
 
====Nested function and function pointer (C)====
With a gcc[[GNU Compiler Collection]] (GCC) extension, a [https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html nested function] can be used and a function pointer can emulate closures, providing the function does not exit the containing scope. The next example is invalid because <code>adder</code> is a top-level definition (depending on compiler version, it could produce a correct result if compiled with no optimizing, i.e., at <code>-O0</code>):
The following example is invalid because <code>adder</code> is a top-level definition (depending on compiler version, it could produce a correct result if compiled without optimization, i.e. at <code>-O0</code>):
 
<syntaxhighlight lang="c">
Line 419 ⟶ 418:
</syntaxhighlight>
 
The capturing of <code>final</code> variables enables you to capturecapturing variables by value. Even if the variable you want to capture is non-<code>final</code>, youit can always copybe itcopied to a temporary <code>final</code> variable just before the class.
 
Capturing of variables by reference can be emulated by using a <code>final</code> reference to a mutable container, for example, a single-element array. The local class will not be able to change the value of the container reference itself, but it will be able to change the contents of the container.
 
With the advent of Java 8's lambda expressions,<ref>{{cite web |url=http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html |title=Lambda Expressions (The Java Tutorials)}}</ref> the closure causes the above code to be executed as:
| url =http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
| title = Lambda Expressions (The Java Tutorials)
}}</ref> the closure causes the above code to be executed as:
 
<syntaxhighlight lang="java">
Line 442 ⟶ 438:
</syntaxhighlight>
 
Local classes are one of the types of [[inner class]] that are declared within the body of a method. Java also supports inner classes that are declared as ''non-static members'' of an enclosing class.<ref>{{cite web
{{cite web | url = https://blogs.oracle.com/darcy/entry/nested_inner_member_and_top
| title = Nested, Inner, Member, and Top-Level Classes}}</ref> They are normally referred to just as "inner classes".<ref>{{cite web
{{cite web | url = http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html
| title = Inner Class Example (The Java Tutorials &gt;: Learning the Java Language &gt;: Classes and Objects)
}}</ref> These are defined in the body of the enclosing class and have full access to instance variables of the enclosing class. Due to their binding to these instance variables, an inner class may only be instantiated with an explicit binding to an instance of the enclosing class using a special syntax.<ref>{{cite web
{{cite web | url = http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
| title = Nested Classes (The Java Tutorials &gt;: Learning the Java Language &gt;: Classes and Objects)
}}</ref>
 
Line 499 ⟶ 495:
=== Blocks (C, C++, Objective-C 2.0) ===
{{Main|Blocks (C language extension)}}
[[Apple Inc.|Apple]] introduced [[Blocks (C language extension)|blocks]], a form of closure, as a nonstandard extension into [[C (programming language)|C]], [[C++]], [[Objective-C 2.0]] and in [[Mac OS X Snow Leopard|Mac OS X 10.6 "Snow Leopard"]] and [[IOS (Apple)|iOS 4]].0]]. Apple made their implementation available for the GCC and clang compilers.
 
Pointers to block and block literals are marked with <code>^</code>. Normal local variables are captured by value when the block is created, and are read-only inside the block. Variables to be captured by reference are marked with <code>__block</code>. Blocks that need to persist outside of the scope they are created in may need to be copied.<ref>{{cite web |url=https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html |title=Blocks Programming Topics |author=<!-- Unstated staff writer --> |date=8 March 2011 |publisher=Apple Inc. |access-date=2011-03-08}}</ref><ref>{{cite web |url=http://thirdcog.eu/pwcblocks/ |title=Programming with C Blocks on Apple Devices |authorlast=Bengtsson |first=Joachim Bengtsson|date=7 July 2010|access-date=2010-09-18|archive-url=https://web.archive.org/web/20101025034928/http://thirdcog.eu/pwcblocks/|archive-date=25 October 2010|url-status=dead}}</ref>
 
<syntaxhighlight lang="objc">
Line 599 ⟶ 595:
Embarcadero C++Builder provides the reserve word __closure to provide a pointer to a method with a similar syntax to a function pointer.<ref>Full documentation can be found at http://docwiki.embarcadero.com/RADStudio/Rio/en/Closure</ref>
 
In standardStandard C you couldallows writewriting a {{mono|[[typedef]]}} for a pointer to a [[function type]] using the following syntax:<syntaxhighlight lang="c++">
typedef void (*TMyFunctionPointer)( void );
</syntaxhighlight>In a similar way you can declare, a {{mono|typedef}} can be declared for a pointer to a method using the followingthis syntax:<syntaxhighlight lang="c++">
typedef void (__closure *TMyMethodPointer)();
</syntaxhighlight>
Line 626 ⟶ 622:
 
== External links ==
*[https://web.archive.org/web/20160510140804/http://library.readscheme.org/page1.html Original "Lambda Papers"]: A classic series of papers by [[Guy L. Steele Jr.]] and [[Gerald Jay Sussman]] discussing, among other things, the versatility of closures in the context of Scheme (where they appear as ''[[lambda calculus|lambda]] expressions'').
* {{cite web
|last=Gafter author |first= Neal Gafter
| date = 2007-01-28
| title = A Definition of Closures
| url = http://gafter.blogspot.com/2007/01/definition-of-closures.html
| author-link = Neal Gafter
}}
* {{cite web
|last1=Bracha author |first1=Gilad [[|author1-link=Gilad Bracha]], [[|last2=Gafter |first2=Neal Gafter]],|last3=Gosling [[|first3=James |author3-link=James Gosling]], [[Peter |last4=von der Ahé]] |first4=Peter
| title = Closures for the Java Programming Language (v0.5)
| url = http://www.javac.info/closures-v05.html
}}
*[http://martinfowler.com/bliki/Closure.html Closures]: An article about closures in [[Dynamic typing|dynamically typed]] imperative languages, by [[Martin Fowler (software engineer)|Martin Fowler]].