Closures/Value capture: Difference between revisions

m
imported>Rowsety Moid
No edit summary
 
(6 intermediate revisions by 5 users not shown)
Line 29:
=={{header|Acornsoft Lisp}}==
 
Since this Lisp is dynamically scoped and does not have any built-in closure mechanism, we have to construct one which we'll call <code>freeze</code>. (The name is inspired by the [[Pop-2]] programming languages's "frozen formals".)
 
('''freeze''' ''varlist lambda-expr'') finds the current values of the variables in ''varlist'' and returns a lambda-expression that is like the original except that, when called, it binds those variables to their captured values. For example, if <code>a</code>'s value is 1 and <code>b</code>'s is 2,
<syntaxhighlight lang="lisp">
( (lambda ((a . 1) (b . 2))
(list a b)) )
</syntaxhighlight>
 
<syntaxhighlight lang="lisp">
Line 47 ⟶ 44:
(list a b c))))
</syntaxhighlight>
 
What does that mean? A cons (''name'' . ''value'') in a lambda-expressions's formal parameters is the syntax for a formal with a default value. The ''value'' is literally the value; it's not an expression that's evaluated. This
 
<syntaxhighlight lang="lisp">
( (lambda ((a . 1) (b . 2))
(list a b c)) )
</syntaxhighlight>
 
calls the function represented by that lambda-expression. Since it does not give the function any arguments, <code>a</code> and <code>b</code> get their default values (which are the values captured by <code>freeze</code>).
 
(Although code within such a 'closure' can assign new values to the captured variables, it would have only a temporary effect and would not change the values seen in subsequent calls to the same closure. That's one sense in which the variable values are "frozen".)
 
Here is the definition of <code>freeze</code>:
Line 641 ⟶ 649:
</syntaxhighlight>
=={{header|Elena}}==
ELENA 46.1x :
<syntaxhighlight lang="elena">import system'routines;
import extensions;
Line 647 ⟶ 655:
public program()
{
var functions := Array.allocate(10).populate::(int i => { ^ i * i} );
functions.forEach::(func) { console.printLine(func()) }
}</syntaxhighlight>
{{out}}
Line 973 ⟶ 981:
{{out}}
<pre>Randomly selecting L[8] = 64</pre>
 
=={{Header|Insitux}}==
 
<syntaxhighlight lang="insitux">
(var funcs (for x (range 11) #(* x x)))
 
[(0 funcs) ((3 funcs)) ((4 funcs))]
</syntaxhighlight>
 
{{out}}
 
<pre>
[#(* x x) 9 16]
</pre>
 
=={{header|Io}}==
<syntaxhighlight lang="text">blist := list(0,1,2,3,4,5,6,7,8,9) map(i,block(i,block(i*i)) call(i))
Line 1,011 ⟶ 1,034:
slist@.(?9) ''
25</syntaxhighlight>
 
===Using temporary locales===
The problem statement "Demonstrate how to create a series of independent closures based on the same template but maintain separate copies of the variable closed over" conflicts with the problem title "Value capture" in languages have sufficient abstraction to distinguish between value capture and variable and variable capture. This conflict even appears in J, and in general cases can require treatment of issues well outside the scope of this task.
 
Still, to address the task description, we should include a "variable capture" implementation, which in J could imply the use of "temporary [[j:Vocabulary/Locales#Summary_of_the_Locale_Mechanism|locales]]" despite the fact that this approach would not satisfy the "simplest fashion possible" requirement.
 
For example, we could define an adverb 'geni' which takes a base function (which in this case will be <code>*:</code> -- a function which squares an argument) and a value (which in this case will be an index), creates a locale where that value will be stored in a variable named <code>i</code> and then returns an anonymous function which takes a reference to the locale (rather than the value) and extracts the value from the locale to generate the result.
 
We'll also use J's nuvoc <code><nowiki>{{</nowiki></code> ... <code><nowiki>}}</nowiki></code> nesting definitional mechanism which implicitly determines the type of a definition instead of explicitly representing the definition types (<code>1 :</code>, <code>2 :</code>, <code>3 :</code>, ...) which discourages nesting blocks.
 
<syntaxhighlight lang=J>
geni=: {{
N=. cocreate''
i__N=. y
N
}}
task=: {{ u {{ u {{ u i__n [ y }} (geni y)`'' }}"0 i. y }}
</syntaxhighlight>
 
This would be really bad form if we were intending to be useful, but - as described above - this approach is somewhat relevant to the task requirements.
 
Example use:
<syntaxhighlight lang=J>
fns=: *: task 10
fns@.3 ''
9
fns@.5 ''
25
fns@.7 ''
49
</syntaxhighlight>
 
 
===Tacit (unorthodox) version===
In J only adverbs and conjunctions (functionals) can produce verbs (functions)... Unless they are forced to cloak as verbs; in this instance, the rank conjunction (“) cloaks as a dyadic verb. (NoteThis thatdoes not work in recent versions of J as this takes advantage of a bug/feature where the interpreter does not produce a result with [http://www.jsoftware.com/help/dictionary/dictb.htm the correct shape]):
 
<syntaxhighlight lang="j"> ( VL=. (<@:((<'"')(0:`)(,^:)&_))"0@:(^&2)@:i. 10 ) NB. Producing a list of boxed anonymous verbs (functions)
Line 1,024 ⟶ 1,079:
{::&VL 5 '' NB. Invoking the 6th verb with a dummy argument ('')
25</syntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|8+}}
Line 2,245 ⟶ 2,301:
Whenever we call a continuation, the <code>(block sqr ...)</code> environment is restored. and the suspended computation inside the block resumes by returning out of the <code>(suspend ...)</code> form normally. The block then executes to completion, returning the <code>(* cap cap)</code> form's value. At that point, our call to the continuation terminates, yielding that value.
=={{header|Wren}}==
<syntaxhighlight lang="ecmascriptwren">var fs = List.filled(10, null)
for (i in 0...fs.count) {
fs[i] = Fn.new { i * i }
Line 2,264 ⟶ 2,320:
Function #8: 64
</pre>
 
=={{header|Yabasic}}==
<syntaxhighlight lang="Yabasic">
6,951

edits