Overview
While there is no doubt Closures are very powerful concept they are fairly complex to implement properly and efficiently.
However, one of the use cases, control block can be simulated using the for each loop without limiting functionality of the blocks involved.
The approach
This approach uses Java 5's for each loop and Iterable/Iterators in a novel way to provide the control functionality.
A single control structure.
In the following example, the lock is acquired the first time the loop is entered and unlocked as the loop exits.
for (ReentrantLock lock : withLock(getLock())) {
assertTrue(lock.isHeldByCurrentThread());
assertTrue(lock.isLocked());
}
assertFalse(getLock().isHeldByCurrentThread());
assertFalse(getLock().isLocked());
Multiple control structures.
The following example has three "loops". The two outer "loops" only loop once but it is a loops ability to return to a previous object which provides closure.
The first loop starts a timer which prints the time taken when the loop finishes. The second loop closes the "out" PrintWriter when it completes . The third loop reads a file one line at a time and closes the resource when finished.
public static void main(String... args) throws FileNotFoundException { for (Void _ : time("file copy")) for (PrintWriter out : closeAfter(new PrintWriter(args[1]))) for (String line : fileByLine(args[0])) out.println(line); }
The implementation
public static Iterable<Void> time(final String message) { return new Once<Void>() { long start = System.nanoTime(); public void after() { System.out.println(message + " took " + (System.nanoTime() - start) / 1000 / 100 / 10.0 + " ms."); } }; }
public static <L extends Lock> Iterable<L> withLock(final L lock) { return new Once<L>() { public void before() { lock.lock(); } public L value() { return lock; } public void after() { lock.unlock(); } }; }
public static <C extends Closeable> Iterable<C> closeAfter(final C closeable) { return new Once<C>() { public C value() { return closeable; } public void after() { System.out.println("<< close " + closeable + ">>"); try { closeable.close(); } catch (IOException ignored) { // ignored. } } }; }
public static Iterable<String> fileByLine(final String filename) throws FileNotFoundException { final BufferedReader br = new BufferedReader(new FileReader(filename)); return new ManyValues<String>() { public String value() throws Exception { return br.readLine(); } public void after() { try { br.close(); } catch (IOException ignored) { // ignored. } } }; }
Limitations.
When the loop break unexpectedly, there is no guarentee when, if ever, the iterator will be closed/finalised.
Escape analysis in Java 7 should help with this as the variable created could be added to the local stack. However ther may still be unexpected behaviour.
One way to support reliable handling is to ensure that the Iterable is closed as soon as the loop exists. The CloseableIterator interface exposes a close method which could be called.
However, it should be possible for this method to be called implicitly without the developer needing to remember to do this.
This can be done two ways:
- code injection to add a finally { if (iterator instanceof CloseableIterator) ((CloseableIterator) iterator.close()) } block. This could be added to Java 5.
- support in the compiler to do this for you. This could be added to Java 7+
Other control blocks.
- An iterator which takes an SQL String and provides a ResultSet foreach result and closes the query when finished. Note: it could return the same resultSet object each time.

Source
The full source and unit tests are available at https://essence.svn.sourceforge.net/svnroot/essence/trunk/essence-control
The built JAR can be downloaded from https://sourceforge.net/project/showfiles.php?group_id=182039
See also
http://www.jroller.com/scolebourne/entry/closures_comparing_control_structures_of
http://www.javac.info/consensus-closures-jsr.html
http://tech.puredanger.com/java7/#closures
http://www.artima.com/weblogs/viewpost.jsp?thread=182412

Comments (4)
Apr 26, 2008
Anonymous says:
Re: "While there is no doubt Closures are very powerful concept they are fairly ...Re: "While there is no doubt Closures are very powerful concept they are fairly complex to implement properly and efficiently."
Why should we care how complex it is to implement? The implementation is done once by Sun Microsystems, but every Java programmer reaps the benefits. HotSpot is already amazingly complex, but having such system code isolate the complexity from user programs is a benefit, not a drawback.
Apr 27, 2008
Peter Lawrey says:
"Why should we care how complex it is to implement?" Good question. I would say..."Why should we care how complex it is to implement?"
Good question. I would say that Closures are more powerful and more complex than Generics.
Generics in Java 5 & 6 still have many things which are not implemented properly, many edge cases most people don't understand and few programmers who can use it effectively.
AFAIK, Sun haven't integrated Closures into Java 7 EA due to resource restrictions. While they might get into Java 7 later in the release process, I am willing to bet its going to be like Generics, only more so.
"HotSpot is already amazingly complex,"
Actually I would say the HotSpot JVM is not so complex. Its the Java library base and the Java language which is increasingly complex. The underlying JVM hasn't changed much in terms of the features supported. e.g. the JVM doesn't really support inner classes so the javac creates accessor methods to allow inner classes to access private members of outer classes. (Rather than the JVM understanding inner classes and allowing this)
"having such system code isolate the complexity from user programs is a benefit, not a drawback."
I agree, reducing and hiding complexity is an asset. However, these systems always have edge cases, it just depends on how bad they are and whether you have the learn these the hard way.
Even simple operations like + and == have edge cases.
Apr 30, 2008
Anonymous says:
This is quite a clever way to achieve the effect of control invocation in Java 5...This is quite a clever way to achieve the effect of control invocation in Java 5, although it is undoubtedly more in the 'hack' department. The ARM closure proposal - linked to CICE - approaches the problem in a not dissimilar way.
Stephen Colebourne
May 16, 2008
Peter Lawrey says:
As you comment in your blog, "ARM proposal is that control structures should onl...As you comment in your blog, "ARM proposal is that control structures should only be added by language designers, and should not be able to be added to libraries."
This is potentially a serious limitation, however I don't believe this has to be the case. The approach here is to provide hooks, like before(), after() which could be called and the only real addition proposed is a method which is always called when the loop ends.
Add Comment