[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