0% found this document useful (0 votes)
55 views10 pages

Closures With Mutable Captured Variables: Javascript

The document shows code examples in various programming languages demonstrating closures capturing mutable variables. In each example: - A variable 'a' is initialized to 5 - A function 'f' is defined that closes over 'a' and returns its argument plus 'a' - Calling 'f' with an argument of 10 initially returns 15 - 'a' is then mutated to 100 - Calling 'f' again with 10 now returns 110, showing 'f' closes over the mutable 'a'

Uploaded by

Javier Goizueta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views10 pages

Closures With Mutable Captured Variables: Javascript

The document shows code examples in various programming languages demonstrating closures capturing mutable variables. In each example: - A variable 'a' is initialized to 5 - A function 'f' is defined that closes over 'a' and returns its argument plus 'a' - Calling 'f' with an argument of 10 initially returns 15 - 'a' is then mutated to 100 - Calling 'f' again with 10 now returns 110, showing 'f' closes over the mutable 'a'

Uploaded by

Javier Goizueta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Closures with mutable captured variables

JavaScript
a = 5;
f = function(x) { return x+a };
console.log(f(10)); // 15
a = 100
console.log(f(10)); // 110

CoffeeScript
a = 5
f = (x)->x+a
console.log f(10) #
1 5
a = 100
console.log f(10) # 1 10

Dart
void main() {
var a = 5;
var f = (x) => x +
a;
print(f(10)); // 1 5
a = 100;
print(f(10)); // 1 10
}

Ruby
a = 5
f = ->(x){x+a}
puts f(10) # => 1
5
a = 100
puts f(10) # => 1 10

Python
a = 5
f = lambda x: x+a
print(f(10)) # 15
a = 100
print(f(10)) # 110

Julia
a = 5
f = (x) -> x+a
print(f(10)) # 1 5
a = 100
print(f(10)) # 1 10

Swift
var a = 5
let f = { (x: Int) -> Int in x+a }
println(f(10)) // 15
a = 100
println(f(10)) // 110

C#
using System;
public class Test
{
delegate int f_type(int x);
public static void Main()
{
int a = 5;
f_type f = (x) => x+a;
System.Console.WriteLine(f(10)); / / 1 5
a = 100;
System.Console.WriteLine(f(10)); / / 1 10
}
}

Go
package main
import "fmt"
func main(){
a := 5
f := func(x int) int { return x+a }
fmt.Println(f(10)) // 15
a = 100
fmt.Println(f(10)) // 110
}

Groovy
def a = 5
def f = { x -> x +
a }
println (10) // 1
f 5
a = 100
println f(10) // 110

R
a <- 5
f <- function(x)x+a
cat("%d", f(10)) # 15
a <- 100
cat("%d",f(10)) # 110

Perl 5
my $a = 5;
my $f = sub { my $x = s
hift; return $x+$a };
print $f->(10), "\n"; # 15
$a = 100;
print $f->(10), "\n"; # 110

Perl 6
my $a = 5;
my $f = -> $x {
$x+$a } ;
print $f(10), " \n"; # 1 5
$a = 100;
print $f(10), " \n"; # 1 10

Lua
a = 5
f = function(x,y) return x+a end
print(f(10)) -- 15
a = 100
print(f(10)) -- 110
Lisp (Scheme) [BiwaScheme, guile]
(define a 5)
(define f (lambda (x) (+ x a )))
(write (f 10)) (newline) ; 1 5
(define a 100)
(write (f 10)) (newline) ; 1 10

Clojure
(def a 5)
(def f (fn [x] (+ x a)))
(println (f 10)) ; 15
(def a 100)
(println (f 10)) ; 110

Smalltalk
a := 5.
f := [ :x |
x +
a ].
(f value: 1 0) p rintNl.
a := 100.
(f value: 1 0) p rintNl !

Scala
object Main extends App {
var a = 5
val f = (x: Integer) => x+a
println(f(10)) // 15
a = 100
println(f(10)) // 110
}

Mathematica
a = 5
f = Function[x, x +
a]
Print[f[10]] (* 1 5 *)
a = 100
Print[f[10]] (* 1 10 *)

C++11 [&]
#include <iostream>
int main() {
int a = 5;
auto f = [&] (int x) { return x + a; }; // or [&a] ...
std::cout << f(10) << std::endl; // 15
a = 100;
std::cout << f(10) << std::endl; // 110
return 0;
}

PHP (>=5.3)
$a = 5;
$f = function($x) use(&$a) { return $x + $a; };
echo $f(10); // 15
echo "\n";
$a = 100;
echo $f(10); // 110
echo "\n";
GCC nested functions & statement expressions (C)
#include <stdio.h>
int main() {
int a = 5;
int (*f)(int x) = ({ int f_(int x) { return x+a; } &f_; });
printf("%d\n", (*f)(10)); /* 15
a = 100;
printf("%d\n", (*f)(10)); /* 110 */
return 0;
}

Maxima
a: 5;
f: lambda([x],x+a);
print(f(10)); /* 15 */
a: 100;
print(f(10)); /* 110 */

RPL
\<< 5 \-> A
\<< \<< A + \>> \-> F
\<< 10 F EVAL 100 @ 15
'A' STO
10 F EVAL \>> @ 110
\>>
\>>
@ Using a 'compiled' variable
\<< 5 \<< \<-A + \>> \-> \<-A F
\<< 10 F EVAL 100 @ 15
'\<-A' STO
10 F EVAL \>> @ 110
\>>
\>>

Factor
USING: kernel locals formatting math ;
IN: test_closures
:: test-closures ( -- )
5 :> a!
[ a + ] :> f
10 f call "%d\n" printf ! 15
100 a!
10 f call "%d\n" printf ! 110
;
note: local variables must be explicitly declared m
utable with !

HP PPL (called from HOME)


#cas
Test() := BEGIN
LOCAL a := 5; // a could be global as well
LOCAL f := (x)->x+a;
PRINT(f(10)); // 15
a := 100;
PRINT(f(10)); // 110
END
#end
// in HOME: Test()
Closures which capture immutable variable-values:
(and languages that disallow mutable state, etc.)

Erlang
% (cannot modify captured variable)
-module(prog).
-export([main/0]).
main () ->
A = 5,
F = fun(X) -> X+A end,
io:fwrite(io_lib:format("F(10): ~p", [F(10)])). % F(10): 15

Elixir
# cand rebind variable, but no actual state change
a = 5
f = fn(x) -> x + a end
IO.puts f.(10) # 5
1
a = 100
IO.puts f.(10) # 15

Haskell
odify captured variable)
(cannot m
module Main where
a = 5
f = \x -> x+a
main = print (f 10) -- 15

OCaml
let a = 5;;
let f x = x+a;;
print_int(f 10);; (* 1
5 * )
print_string("\n");;
a = 100;;
print_int(f 10);; (* 1 5 * )
print_string("\n");;

Java 8
// local variables referenced from a lambda expression must be f inal or effectively final
public class Test
{
interface Ftype { public Integer call(Integer x); }
public static void main(String[] args)
{
Integer a = 5;
Ftype f = (x) -> x+a;
System.out.print(f.call(10)); // 15
// a = 100; <-- this would provoke a compilation e rror
// System.out.print(f.call(10));
}
}

Java
// using anonymous inner class; same situation as with Java 8 lambdas: a must be e
ffectively final
local variables referenced from a lambda expression must be final or effectively f inal
public class Test
{
interface Ftype { public Integer call(Integer x); }
p ublic static void main(String[] args)
{
final Integer a = 5; // in Java 7 this has to be declared f inal in 8 it i s not necessary
Ftype f = new Ftype() {
public Integer call(Integer x) { return a+x; };
};
System.out.println(f.call(10)); // 15
// a = 100; <-- this would provoke a compilation error e ven if a was n ot explicitly final
// System.out.println(f.call(10));
}
}

C++11 [=]
#include <iostream>
int main() {
int a = 5;
auto f = [=] (int x) { return x + a; }; // or [a] ...
std::cout << f(10) << std::endl; // 15
a = 100;
std::cout << f(10) << std::endl; // 15
return 0;
}

Objective-C (clang blocks extension)


#import <Foundation/Foundation.h>
int main(void) {
int a = 5;
int (^f)(int) = ^(int x) { return x + a; };
NSLog(@"%d", f(10)); /* 15 */
a = 100;
NSLog(@"%d", f(10)); /* 15 */
return 0;
}
C (clang blocks extension)
#include <stdio.h>
int main() {
int a = 5;
int (^f)(int) = ^(int x) { return x + a; };
printf("%d\n", f(10)); /* 15 */
a = 100;
printf("%d\n", f(10)); /* 15 */
return 0;
}

GNU Octave
a = 5
f = @(x)x+a
disp(f(10)) # 1 5
a = 100
disp(f(10)) # 1 5

HP PPL (called from CAS)


#cas
Test() := BEGIN
LOCAL a := 5; // a could be global as well
LOCAL f := (x)->x+a;
PRINT(f(10)); // 15
a := 100;
PRINT(f(10)); // 15
END
#end
// in CAS: Test()

Techniques to inject immutable values in closures:


CoffeeScript (do)
a = 5
f = do (a) -> (x) -> x+a
console.log f(10) # 15
a = 100
console.log f(10) # 15
but the solution if of limited application: if protects from rebounded variables, but not from mutable
objects e.g.:
a = [5]
f = do (a) -> (x) -> x+a[0]
console.log f(10) # 15
a[0] = 100
console.log f(10) # 110 doh!

Factor (curry)
USING: kernel locals formatting math ;
IN: test_closures
:: test-closures ( -- )
5 :> a!
a [ + ] curry :> f
10 f call "%d\n" printf ! 15
100 a!
10 f call "%d\n" printf ! 15
;

JavasScript
a = 5;
f = function(a) {
return function(x) { return x+a };
}(a);
console.log(f(10)); // 15
a = 100
console.log(f(10)); // 15
ame limitations as with CoffeeScript
# s

Ruby >= 1.9.2


def with_local(&blk)
Object.new.instance_exec(*blk.parameters.map{|kind, var| blk.binding.eval(var.to_s), &blk)
end
a = 5
f = with_local { |a| ->(x){ x + a } }
puts f[10] # 15
a = 100
puts f[10] # 15
# Note that dup is not a deep copy, so a contents may still be mutable for certain types:
# e ven if we redefine with_local to dup the variables (
def with_local(&blk)
Object.new.instance_exec(*blk.parameters.map{|kind, var| blk.binding.eval(var.to_s).tap{|x|
x.dup rescue x}}, &blk)
end

[
a = [5]]
f = w ith_local { |a| ->(x){ x + a[0][0] } }
puts f[10] # 15
a[0][0] = 100
puts f[10] # 110

Ruby
for Ruby < 1.9.2 wed have add another identifier; note that for Ruby < 1.9 the inner a should be
renamed
def with_local(*args)
yield *args.map(&:dup)
end
a = 5
f = with_local(a) { |a| ->(x){ x + a } }
puts f[10] # 15
a = 100
puts f[10] # 15

Mathematica
a = 5
f = With[{a = a
}, F
unction[{x}, x + a]] (* Module could also be used *)
Print[f[10]] (* 1 5 *)
a = 100
Print[f[10]] (* 1 5 *)

Java 8
hat Java protection against u
Note t sing non-(effectively)-final v ariables in lambdas is not deep, so
that t he mutable behaviour can be a chieved just by wrapping the v ariables:

public class Test


{
interface Ftype { public Integer call(Integer x); }
static class Wrapper {
public int value = 10;
}
public static void main(String[] args)
{
Wrapper a = new Wrapper();
a.value = 5;
Ftype f = (x) -> x+a.value;
System.out.println(f.call(10)); // 15
a.value = 100;
System.out.println(f.call(10)); // 110
}
}

Java
hat Java protection against u
Note t sing non-(effectively)-final v ariables in lambdas is not deep, so
that t he mutable behaviour can be a chieved just by wrapping the v ariables:

public class Test


{
interface Ftype { public int call(int x); }
static class Wrapper {
public int value = 10;
}
public static void main(String[] args)
{
final Wrapper a = new Wrapper();
a.value = 5;
Ftype f = new Ftype() {
public int call(int x) { return a
.value+x; };
};
System.out.println(f.call(10)); // 1 5
a.value = 100;
System.out.println(f.call(10)); // 1 10
}
}

C++11
Note an a rray captured by value is immutable:
#include <iostream>
int main() {
int a[1] = {5};
auto f = [=] (int x) { return x + a[0]; }; // or [a] ...
std::cout << f(10) << std::endl; // 15
a[0] = 100;
std::cout << f(10) << std::endl; // 15
return 0;
}
But using pointers will of course defeat the mutability protection:
#include <iostream>
int main() {
int *a = new int;
*a = 5;
auto f = [=] (int x) { return x + *a; }; // or [a] ...
std::cout << f(10) << std::endl; // 15
*a = 100;
std::cout << f(10) << std::endl; // 110
return 0;
}

Resources:
http://ideone.com/
http://www.compilejava.net/
http://repl.it/
http://perlcabal.org/~fglock/perlito5.html
http://octave-online.net/
http://sandbox.onlinephpfunctions.com/
https://try.dartlang.org/
http://maxima-online.org/
http://www.tutorialspoint.com/

Haskell : TODO explore using IORef and do notation

Visual Basic.NET
Imports System
Public Class Test
Public Shared Sub Main()
Dim a = 5
Dim f = Function(x) x+a
Console.WriteLine(f(10)) ' 15
a = 100
Console.WriteLine(f(100)) ' ?
End Sub
End Class

TCL has no closures


set a 5
set f {{x} {expr {$x+$a}}}
puts [apply $f 10] ;# error: a not defined

You might also like