There has been a lot of talk on Javalobby recently about adding closures to Java. But how can this be done without destroying the style of Java?
Groovy shows one way to add closures. But groovy has the ability to create syntax, change classes and do other strange stuff that is just too way out for Java itself. So I though I'd do an experiment to see if I could figure out a way to add closures to Java following a more java style.
I started with a use case I wanted to solve, the dreaded resource close:
InputStream in = null; try { in = new FileInputStream(file); in.read(); ... } finally { if (in != null) { try ( in.close(); } catch (IOException ex) { } } }
I then played around with some ideas.
My preferred solution was:
do.CloseAfter (InputStream in) { in = new FileInputStream(file); in.read(); ... }
I saw the main benefits as being more readable, shorter, removing the common close code, scoping the variable and reducing errors. Importantly, a current Java programmer would grok the new way of woring very quickly (no complex syntax).
The key was using the do keyword to identify the special code. I believe that this keyword-usage is much more Java-style than arbitrary symbols like ->.
CloseAfter
would just be a regular Java class, just limited to have one method:
public class CloseAfter implements ClosureManager { public void execute(InputStream in) { try { call(in); } finally { if (in != null) { try ( in.close(); } catch (IOException ex) { } } } } }
For this common case, it would be a JDK class.
Once I'd done all this and convinced myself that the compiler could implement it easily (by copying the CloseAfter code directly into the original method) I had a sudden realisation - this wasn't really closures, but surrounded code blocks.
Nevertheless, it could be very, very useful, for example to do commit and rollback...
do.DBTransaction (Connection con) { ... }
Kind of like AOP-lite :-)
I just have this sense that a syntax like this would be easy to add to Java, and solve 80% of the issues that full-blown closures tackle (with 20% of the complexity). Opinions welcome :-)
For good information on what a closure is check out http://c2.com/cgi/wiki?WhatIsClosure.
ReplyDeleteKirk, I understand that this isn't closures. However, I do believe that you can't have closures in Java without something like this.
ReplyDeleteIn groovy, they added a forEach() method to Collection. In Java we can't do that. So, we need some way to 'manage' the closure. That is what my proposal actually covers.
My final comment is that once you do this, you may find that 80% of the times you think you need closures, you actually don't - a surrounded code block is sufficient.
Looks like what you are asking for is actually first class functions in Java.
ReplyDeleteThe following scenario occurs often.
You know that after using your resource, you want to close it whether or not it succeeded. So, if you have a method m in class c that does the work, you don't want to invoke the code in the finally block.
Assuming functions could be easily passed in, the code would look somewhat like this:
public void useResource(Function f, Resource r) {
try {
f(r);
}
finally {
r.close();
}
}
This method could then be used as often as necessary secure in the knowledge that the Resource would always be closed. Standard error handling may also be easily included with a catch block or two.
But this is definitely not what closures are about.