Closures/Value capture: Difference between revisions

m
m (syntax highlighting fixup automation)
 
(12 intermediate revisions by 7 users not shown)
Line 1:
[[Category:Functions and subroutines]]
{{task}}
 
Line 15 ⟶ 16:
 
See also: [[Multiple distinct objects]]
 
=={{header|11l}}==
<syntaxhighlight lang="11l">[(() -> Int)] funcs
Line 26:
9
</pre>
 
=={{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">
(freeze '(a b) '(lambda (c) (list a b c)))
</syntaxhighlight>
 
would return
 
<syntaxhighlight lang="lisp">
(lambda (c)
((lambda ((a . 1) (b . 2))
(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>:
 
<syntaxhighlight lang="lisp">
(defun freeze (_fvars_ _lambda-expr_)
(freeze-vars
(mapc cons _fvars_ (mapc eval _fvars_))
(cadr _lambda-expr_)
(cddr _lambda-expr_)))
 
(defun freeze-vars (bindings lvars lbody)
(list 'lambda lvars
(list (cons 'lambda (cons bindings lbody)))))
</syntaxhighlight>
 
Once we have <code>freeze</code>, we can create a list of square-returning functions and then call them:
 
<syntaxhighlight lang="lisp">
(defun range (from to)
(cond ((greaterp from to) '())
(t (cons from (range (add1 from) to)))))
 
(defun example ()
(mapc '(lambda (f) (f))
(mapc '(lambda (i)
(freeze '(i) '(lambda () (times i i))))
(range 1 10))))
</syntaxhighlight>
 
{{Out}}
 
<code>(example)</code> returns
<pre>(1 4 9 16 25 36 49 64 81 100)</pre>
 
=={{header|Ada}}==
Line 64 ⟶ 126:
{{out}}
<pre> 1 4 9 16 25 36 49 64 81</pre>
 
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|2.8}}
Line 89 ⟶ 150:
 
Using partial parametrization as proposed in Algol Bulletin by Charles Lindsey. Algol68G does not support binding ''all'' actual parameters "partially" without deproceduring, so a PROC(BOOL)INT mode is used instead of a PROC INT. The variable ''captured i'' is passed twice, once by reference and once by value, to demonstrate that it is possible to capture both ways, and a little extra code is added to show that the closure can modify the captured variable.
 
=={{header|AntLang}}==
<syntaxhighlight lang="AntLang">fns: {n: x; {n expt 2}} map range[10]
(8 elem fns)[]</syntaxhighlight>
 
=={{header|AppleScript}}==
{{trans|JavaScript}}
Line 173 ⟶ 232:
end mReturn</syntaxhighlight>
{{Out}}
<pre>9</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">funcs: [ø]
 
loop 1..10 'f ->
'funcs ++ function [] with 'f [
f * f
]
 
print call funcs\3 []</syntaxhighlight>
 
{{out}}
 
<pre>9</pre>
 
Line 217 ⟶ 289:
Essentially, a function has been constructed for each value to be squared (10 down to 1). The cp operator ensures that we generate a fresh copy of the number to be squared, as well as the code for multiplying, {*}.
In the final each loop, we eval each of the constructed functions and output the result.
 
=={{header|Bracmat}}==
<syntaxhighlight lang="bracmat">( -1:?i
Line 238 ⟶ 309:
49
64</pre>
 
=={{header|C}}==
 
Line 353 ⟶ 423:
0
</pre>
 
=={{header|C sharp|C#}}==
===Using Linq===
Line 418 ⟶ 487:
49
64</syntaxhighlight>
 
=={{header|C++}}==
{{works with|C++11}}
Line 445 ⟶ 513:
81
</pre>
 
=={{header|Ceylon}}==
<syntaxhighlight lang="ceylon">shared void run() {
Line 456 ⟶ 523:
}
}</syntaxhighlight>
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(def funcs (map #(fn [] (* % %)) (range 11)))
Line 463 ⟶ 529:
<pre>9
16</pre>
 
=={{header|CoffeeScript}}==
 
Line 473 ⟶ 538:
console.log func() for func in funcs
</syntaxhighlight>
 
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">CL-USER> (defparameter alist
Line 486 ⟶ 550:
 
The ''loop'' mutates its binding ''i''. The purpose of <code>(let ((i i)) ...)</code> is to create a different binding ''i'' for each ''lambda'' to capture. Otherwise, all 10 lambdas would capture the same binding and return 100.
 
=={{header|D}}==
===Less Functional Version===
Line 509 ⟶ 572:
{{out}}
<pre>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]</pre>
 
=={{header|Delphi}}==
{{works with|Delphi 2009}}
Line 551 ⟶ 613:
81
</pre>
 
=={{header|Dyalect}}==
Dyalect captures variables by reference, therefore a way to achieve this is to capture a variable through a closure which in its turn returns a anonymous function like so:
Line 580 ⟶ 641:
 
This is similar to a JavaScript (ES6) solution.
 
=={{header|EchoLisp}}==
<syntaxhighlight lang="scheme">
Line 588 ⟶ 648:
→ 25
</syntaxhighlight>
 
=={{header|Elena}}==
ELENA 46.1x :
<syntaxhighlight lang="elena">import system'routines;
import extensions;
Line 596 ⟶ 655:
public program()
{
var functions := Array.allocate(10).populate::(int i => { ^ i * i} );
functions.forEach::(func) { console.printLine(func()) }
}</syntaxhighlight>
{{out}}
Line 629 ⟶ 688:
81
</pre>
 
=={{header|Emacs Lisp}}==
As of Emacs 24.3, lexical closures are supported, therefore alleviating hacks such as lexical-let.
Line 640 ⟶ 698:
'(1 2 3 4 5 6 7 8 9 10)))
;; => (1 4 9 16 25 36 49 64 81 100)</syntaxhighlight>
 
=={{header|Erlang}}==
Erlang uses lexical scoping and has anonymous functions.
Line 672 ⟶ 729:
ok
</pre>
 
=={{header|F_Sharp|F#}}==
Nearly identical to OCaml
Line 715 ⟶ 771:
81
</pre>
 
=={{header|Factor}}==
===Using lexical variables===
Line 756 ⟶ 811:
] each
drop</syntaxhighlight>
 
=={{header|Fantom}}==
 
Line 783 ⟶ 837:
Function at index: 7 outputs 49
</pre>
 
=={{header|Forth}}==
<syntaxhighlight lang="forth">: xt-array here { a }
Line 795 ⟶ 848:
 
<syntaxhighlight lang="forth">25</syntaxhighlight>
 
=={{header|FreeBASIC}}==
 
Line 846 ⟶ 898:
81
</pre>
 
=={{header|Go}}==
<syntaxhighlight lang="go">package main
Line 868 ⟶ 919:
func #3: 9
</pre>
 
=={{header|Groovy}}==
Solution:
Line 881 ⟶ 931:
{{out}}
<pre>49</pre>
 
=={{header|Haskell}}==
 
Line 906 ⟶ 955:
> fs !! 8 $ undefined
81</syntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
This uses Unicon specific calling sequences for co-expressions. It can be made to run under Icon by modifying the calling syntax.
Line 933 ⟶ 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))
writeln(blist at(3) call) // prints 9</syntaxhighlight>
 
=={{header|J}}==
 
Line 973 ⟶ 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,023 ⟶ 1,116:
}
}</syntaxhighlight>
 
=={{header|JavaScript}}==
 
Line 1,093 ⟶ 1,185:
9
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">funcs = [ () -> i^2 for i = 1:10 ]</syntaxhighlight>
Line 1,101 ⟶ 1,192:
49
</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">// version 1.0.6
Line 1,124 ⟶ 1,214:
64
</pre>
 
=={{header|Lambdatalk}}==
 
Line 1,140 ⟶ 1,229:
-> 16
</syntaxhighlight>
 
=={{header|Latitude}}==
 
Line 1,163 ⟶ 1,251:
64
81</pre>
 
=={{header|LFE}}==
 
Line 1,193 ⟶ 1,280:
 
</syntaxhighlight>
 
=={{header|Lingo}}==
 
Line 1,249 ⟶ 1,335:
put call(funcs[7], _movie, 4, 5, 6)
-- 64</syntaxhighlight>
 
=={{header|Logtalk}}==
The example that follow uses Logtalk's native support for lambda expressions.
Line 1,284 ⟶ 1,369:
yes
</syntaxhighlight>
 
=={{header|Lua}}==
<syntaxhighlight lang="Lua">
Line 1,298 ⟶ 1,382:
9
</pre>
 
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="M2000 Interpreter">
Line 1,363 ⟶ 1,446:
 
</syntaxhighlight>
 
=={{header|Maple}}==
<syntaxhighlight lang="Maple">> L := map( i -> (() -> i^2), [seq](1..10) ):
Line 1,371 ⟶ 1,453:
16
</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="Mathematica">Function[i, i^2 &] /@ Range@10
Line 1,378 ⟶ 1,459:
%[[2]][]
->4</syntaxhighlight>
 
=={{header|Nemerle}}==
<syntaxhighlight lang="Nemerle">using System.Console;
Line 1,396 ⟶ 1,476:
<pre>16
4</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">var funcs: seq[proc(): int] = @[]
Line 1,407 ⟶ 1,486:
for i in 0..8:
echo "func[", i, "]: ", funcs[i]()</syntaxhighlight>
 
=={{header|Objeck}}==
<syntaxhighlight lang="objeck">use Collection.Generic;
Line 1,440 ⟶ 1,518:
81
</pre>
 
=={{header|Objective-C}}==
{{works with|Cocoa|Mac OS X 10.6+}} with ARC
Line 1,451 ⟶ 1,528:
NSLog(@"%d", foo()); // logs "9"
</syntaxhighlight>
 
=={{header|OCaml}}==
 
Line 1,473 ⟶ 1,549:
fun.(6) = 36
</pre>
 
=={{header|Oforth}}==
<syntaxhighlight lang="Oforth">: newClosure(i) #[ i sq ] ;
Line 1,482 ⟶ 1,557:
49
</pre>
 
=={{header|PARI/GP}}==
{{works with|PARI/GP|2.4.2 and above}}
Line 1,489 ⟶ 1,563:
{{out}}
<pre>%1 = 25</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">my @f = map(sub { $_ * $_ }, 0 .. 9); # @f is an array of subs
Line 1,505 ⟶ 1,578:
64
</pre>
 
=={{header|Phix}}==
Phix does not support closures, but they seem easy enough to emulate
<!--<syntaxhighlight lang="Phixphix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #000080;font-style:italic;">-- First some generic handling stuff, handles partial_args
Line 1,559 ⟶ 1,631:
 
A dictionary based approach may prove somewhat easier:
<!--<syntaxhighlight lang="Phixphix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">square</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">tid</span><span style="color: #0000FF;">)</span>
Line 1,576 ⟶ 1,648:
<!--</syntaxhighlight>-->
same output, for both tests
 
=={{header|Phixmonti}}==
<syntaxhighlight lang="Phixmontiphixmonti">def power2
dup *
enddef
Line 1,595 ⟶ 1,666:
i get i swap exec print " " print
endfor</syntaxhighlight>
 
=={{header|PHP}}==
{{works with|PHP|5.3+}}
Line 1,615 ⟶ 1,685:
echo $funcs[3](), "\n"; // prints 9
?></syntaxhighlight>
 
=={{header|PicoLisp}}==
<syntaxhighlight lang="PicoLisp">(setq FunList
Line 1,627 ⟶ 1,696:
: ((get FunList 8))
-> 64</pre>
 
=={{header|Pike}}==
<syntaxhighlight lang="Pike">array funcs = ({});
Line 1,642 ⟶ 1,710:
});
}</syntaxhighlight>
 
=={{header|PowerShell}}==
I'm not sure that I understood the question/task. This task seems to be the same as the 'Accumulator Factory' task.
Line 1,705 ⟶ 1,772:
20 400
</pre>
 
=={{header|Prolog}}==
Works with SWI-Prolog and module '''lambda.pl''' from '''Ulrich Neumerkel'''. <br>
Line 1,739 ⟶ 1,805:
true.
</pre>
 
=={{header|Python}}==
The naive way does not work:
Line 1,772 ⟶ 1,837:
<syntaxhighlight lang="python">funcs=[eval("lambda:%s"%i**2)for i in range(10)]
print funcs[3]() # prints 9</syntaxhighlight>
 
=={{header|Quackery}}==
 
Line 1,788 ⟶ 1,852:
 
<pre>25</pre>
 
=={{header|R}}==
 
Line 1,866 ⟶ 1,929:
[1] 16
</pre>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
Line 1,877 ⟶ 1,939:
'(0 1 4 9 16 25 36 49 64 81)
</syntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
Line 1,900 ⟶ 1,961:
Or equivalently, using a more functional notation:
<syntaxhighlight lang="raku" line>say .() for pick *, map -> $i { -> {$i * $i} }, ^10</syntaxhighlight>
 
=={{header|Red}}==
<syntaxhighlight lang="Red">
Line 1,908 ⟶ 1,968:
== 49
</syntaxhighlight>
 
=={{header|REXX}}==
This REXX version supports both a one─ and zero─based list &nbsp; (it can be specified at the command line.)
Line 1,952 ⟶ 2,011:
function .0 returned 100
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
Line 1,975 ⟶ 2,033:
49
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">procs = Array.new(10){|i| ->{i*i} } # -> creates a lambda
Line 1,981 ⟶ 2,038:
 
In Ruby, lambdas (and procs) are closures.
 
=={{header|Rust}}==
One note here about referencing values and capturing values: <br>
Line 1,993 ⟶ 2,049:
{{out}}
<pre>7th val: 49</pre>
 
=={{header|Scala}}==
<syntaxhighlight lang="scala">val closures=for(i <- 0 to 9) yield (()=>i*i)
Line 2,010 ⟶ 2,065:
---
49</pre>
 
=={{header|Scheme}}==
 
Line 2,040 ⟶ 2,094:
(newline)
</syntaxhighlight>
 
=={{header|Sidef}}==
<syntaxhighlight lang="ruby">var f = (
Line 2,082 ⟶ 2,135:
81
</pre>
 
=={{header|Smalltalk}}==
<syntaxhighlight lang="smalltalk">funcs := (1 to: 10) collect: [ :i | [ i * i ] ] .
Line 2,088 ⟶ 2,140:
{{out}}
<pre>9</pre>
 
=={{header|Sparkling}}==
In Sparkling, upvalues (variables in the closure) are captured by value.
Line 2,112 ⟶ 2,163:
print(fnlist[3]()); // prints 9
print(fnlist[5]()); // prints 25</syntaxhighlight>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="Standard ML">
Line 2,120 ⟶ 2,170:
val it = [0,1,4,9,16,25,36,49,64,81] : int list
</syntaxhighlight>
 
=={{header|Swift}}==
By default, Swift captures variables by reference. A naive implementation like the following C-style for loop does not work:
Line 2,146 ⟶ 2,195:
<syntaxhighlight lang="swift">let funcs = [] + map(0..<10) {i in { i * i }}
println(funcs[3]()) // prints 9</syntaxhighlight>
 
=={{header|Tcl}}==
Tcl does not support closures (either value-capturing or variable-capturing) by default, but value-capturing closures are easy to emulate.
Line 2,193 ⟶ 2,241:
8=>64
</pre>
 
=={{header|TXR}}==
 
Line 2,253 ⟶ 2,300:
 
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,291 ⟶ 2,337:
next
</syntaxhighlight>
 
=={{header|zkl}}==
Create a closure of the index over a square function
Line 2,311 ⟶ 2,356:
L(0,1,4,9,16,25,36,49,64,81)
</pre>
 
{{omit from|BASIC}}
{{omit from|Brlcad}}
Line 2,318 ⟶ 2,362:
{{omit from|PureBasic}}
{{omit from|ZX Spectrum Basic}}
 
[[Category:Functions and subroutines]]
6,951

edits