Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Closure (computer programming)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== 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. These examples in ECMAScript and Smalltalk highlight the difference: <syntaxhighlight lang="smalltalk"> "Smalltalk" foo | xs | xs := #(1 2 3 4). xs do: [:x | ^x]. ^0 bar Transcript show: (self foo printString) "prints 1" </syntaxhighlight> <syntaxhighlight lang="javascript"> // ECMAScript function foo() { var xs = [1, 2, 3, 4]; xs.forEach(function (x) { return x; }); return 0; } alert(foo()); // prints 0 </syntaxhighlight> The above code snippets will behave differently because the Smalltalk <code>^</code> operator and the JavaScript <code>return</code> operator are not analogous. In the ECMAScript example, <code>return x</code> will leave the inner closure to begin a new iteration of the <code>forEach</code> loop, whereas in the Smalltalk example, <code>^x</code> will abort the loop and return from the method <code>foo</code>. [[Common Lisp]] provides a construct that can express either of the above actions: Lisp <code>(return-from foo x)</code> behaves as [[Smalltalk]] <code>^x</code>, while Lisp <code>(return-from nil x)</code> behaves as [[JavaScript]] <code>return x</code>. Hence, Smalltalk makes it possible for a captured escape continuation to outlive the extent in which it can be successfully invoked. Consider: <syntaxhighlight lang="smalltalk"> "Smalltalk" foo ^[ :x | ^x ] bar | f | f := self foo. f value: 123 "error!" </syntaxhighlight> When the closure returned by the method <code>foo</code> is invoked, it attempts to return a value from the invocation of <code>foo</code> that created the closure. Since that call has already returned and the Smalltalk method invocation model does not follow the [[spaghetti stack]] discipline to facilitate multiple returns, this operation results in an error. Some languages, such as [[Ruby (programming language)|Ruby]], enable the programmer to choose the way <code>return</code> is captured. An example in Ruby: <syntaxhighlight lang="ruby"> # Ruby # Closure using a Proc def foo f = Proc.new { return "return from foo from inside proc" } f.call # control leaves foo here return "return from foo" end # Closure using a lambda def bar f = lambda { return "return from lambda" } f.call # control does not leave bar here return "return from bar" end puts foo # prints "return from foo from inside proc" puts bar # prints "return from bar" </syntaxhighlight> Both <code>Proc.new</code> and <code>lambda</code> in this example are ways to create a closure, but semantics of the closures thus created are different with respect to the <code>return</code> statement. In [[Scheme (programming language)|Scheme]], definition and scope of the <code>return</code> control statement is explicit (and only arbitrarily named 'return' for the sake of the example). The following is a direct translation of the Ruby sample. <syntaxhighlight lang="Scheme"> ; Scheme (define call/cc call-with-current-continuation) (define (foo) (call/cc (lambda (return) (define (f) (return "return from foo from inside proc")) (f) ; control leaves foo here (return "return from foo")))) (define (bar) (call/cc (lambda (return) (define (f) (call/cc (lambda (return) (return "return from lambda")))) (f) ; control does not leave bar here (return "return from bar")))) (display (foo)) ; prints "return from foo from inside proc" (newline) (display (bar)) ; prints "return from bar" </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)