[Prev][Next][Index][Thread]
Re: Closures
> Hi, forgive me if I am being dense here, but could somebody please
> give me a (preferably short) Java code fragment, that exposes the
> "shared binding" assignment problem?
Start with the first definition of Test below. It's one that actually
works in Java, because the "closures" refer to a RefInt object that
contains an int, and so there's no assignment to i, only to i.val.
In addition, i must be final or else you get compile-time errors
like this one:
Test.java:7: Attempt to use a non-final variable i from a different method.
>From enclosing blocks, only final local variables are available.
i.val = i.val + 1;
class Test {
public static void main(String[] argv) {
final RefInt i = new RefInt(0);
Runnable closure1 = new Runnable() {
public void run() {
i.val = i.val + 1;
}
};
Runnable closure2 = new Runnable() {
public void run() {
i.val = i.val + 3;
}
};
System.out.println("Initial value = " + i.val);
for (int count = 1; count <= 10; count++) {
System.out.print("Iteration " + count + ": ");
closure1.run();
System.out.print("after closure1, " + i.val + "; ");
closure2.run();
System.out.println("after closure2, " + i.val + ". ");
}
}
static class RefInt {
int val;
RefInt(int init) { val = init; }
}
}
Here's the output:
Initial value = 0
Iteration 1: after closure1, 1; after closure2, 4.
Iteration 2: after closure1, 5; after closure2, 8.
Iteration 3: after closure1, 9; after closure2, 12.
Iteration 4: after closure1, 13; after closure2, 16.
Iteration 5: after closure1, 17; after closure2, 20.
Iteration 6: after closure1, 21; after closure2, 24.
Iteration 7: after closure1, 25; after closure2, 28.
Iteration 8: after closure1, 29; after closure2, 32.
Iteration 9: after closure1, 33; after closure2, 36.
Iteration 10: after closure1, 37; after closure2, 40.
The idea is that if Java had the "shared binding" semantics, then
the the following program would also work:
class Test {
public static void main(String[] argv) {
int i = 0; // not final, not RefInt
Runnable closure1 = new Runnable() {
public void run() {
i = i + 1; // can assign to it
}
};
Runnable closure2 = new Runnable() {
public void run() {
i = i + 3; // in both closures
}
};
System.out.println("Initial value = " + i);
// Show that assignments in each closure affect the other:
for (int count = 1; count <= 10; count++) {
System.out.print("Iteration " + count + ": ");
closure1.run();
System.out.print("after closure1, " + i + "; ");
closure2.run();
System.out.println("after closure2, " + i + ". ");
}
}
}
Apologies for Java code in Dylan group. Of course, this is all much
nicer in Dylan.
-- Jeff