Instructor: James Riely
javac
requires final i
from enclosing scope
for (int i = 0; i < 5; i++) {
new Thread (new Runnable () {
public void run () { /* rejected: i mutates */
while (true) { System.out.print (i); }
}
}).start ();
}
for (int i = 0; i < 5; i++) {
int x = i;
new Thread (new Runnable () {
public void run () { /* accepted: x never mutates */
while (true) { System.out.print (x); }
}
}).start ();
}
for (int i = 0; i < 5; i++) {
new Thread (() -> { /* rejected: i mutates */
while (true) { System.out.print (i); }
}).start ();
}
for (int i = 0; i < 5; i++) {
int x = i;
new Thread (() => { /* accepted: x never mutates */
while (true) { System.out.print (x); }
}).start ();
}
var i = 1
while i < 5 do
Thread (() =>
while true do print (i)
).start
i = i + 1
var i = 1
while i < 5 do
val x = i
Thread (() =>
while true do print (x)
).start
i = i + 1
def main(args: Array[String]): Unit =
for i <- (1 to 4) do
Thread (() =>
while true do print (i)
).start
outer
is called
x
outer
returns nested function inner
x
from outer
's AR
outer
's AR and x
ends
inner
is called
x
from outer
's AR
def outer (x:A) : B=>C =
def inner (y:B) : C =
//...use x and y...
inner
inner
x
def outer (x:A) : B=>C =
def inner (y:B) : C =
...use x and y...
inner
inner
x
and u
inner
sees updated u
?
u
to be immutable?
def outer (x:A) : B=>C =
var u:A = x
def inner (y:B) : C =
//...use u and y...
u = u + 1
inner
u
inner
x
u
(on heap)
def outer (x:A) : B=>C =
var u:A = x
def inner (y:B) : C =
//...use u and y...
u = u + 1
inner
object Closure:
def outer (x:Int) : Boolean=>Int =
def inner (y:Boolean) : Int =
x + (if y then 0 else 1)
inner
$ scalac Closure.scala
$ ls -1 Closure*
Closure$$anonfun$outer$1.class
Closure.class
Closure$.class
Closure.scala
x
copied into field x$1
$ javap -p Closure
Compiled from "Closure.scala"
public final class Closure {
public static scala.Function1<java.lang.Object, java.lang.Object> outer(int);
}
$ javap -p Closure\$\$anonfun\$outer\$1
Compiled from "Closure.scala"
public final class Closure$$anonfun$outer$1 extends scala.runtime.AbstractFunction1<java.lang.Object, java.lang.Object> {
private final int x$1;
public final int apply(boolean);
public Closure$$anonfun$outer$1(int);
}
u
is a var
declaration, so is mutable
object Closure:
def outer (x:Int) : Boolean=>Int =
var u:Int = x
def inner (y:Boolean) : Int =
x + u + (if y then 0 else 1)
inner
x
copied into field x$1
u
shared on heap via reference in field u$1
$ javap -p Closure\$\$anonfun\$outer\$1
Compiled from "Closure.scala"
public final class Closure$$anonfun$outer$1 extends scala.runtime.AbstractFunction1<java.lang.Object, java.lang.Object> {
private final int x$1;
private final scala.runtime.IntRef u$1;
public final int apply(boolean);
public Closure$$anonfun$outer$1(int, scala.runtime.IntRef);
}