Friday, February 13, 2009

Language Parity: Closures and the Java VM

A video of my talk at the September 2008 JVM Language Summit has been posted. It's a discussion of how Java SE is tilted toward supporting the Java language at the expense of other languages, and what we might do about it.

12 comments:

Fatih Coşkun said...

Thanks, great talk.

Every single day at work I wish we had closures in Java: "this library would be easier to write, that code would be easier to read".

I graduated not long ago in 2007, and having closures would not make my head explode. It would be a relief!

David said...

Hi Neal,

I'm not really aware of how big the BGGA change would be.

Does it produce bytecode that cannot be produce now ? If so, it's just a syntaxic enhancment ?
If not, it means Java is not currently turing-complete ?

I mean, does it only solve ugliness of anonymous classes ?

Thanks.

Fatih, I graduated in 2003 (i'm 30) and, well, closures do make my head explode. I can't read them. Or more precisely, I don't know how to read it. I'm too old or too stupid, it seems.

Neal Gafter said...

@David: BGGA allows you to express concepts in the language that cannot be directly expressed today. While the set of problems you can solve doesn't increase, the set of problems you can solve using simple and readable code (without repeating yourself) does increase. Expressiveness in that sense is why we program in high-level languages rather than assembly.

As far as knowing how to read closures, that comes quickly once you start using them.

Fatih Coşkun said...

@David
Of course, there is a little drawback if you express in 5 lines of code (with closures) what you normally would express in 50 lines of code (conventional Java). The 5 lines of code may at first seem to be very complex. Though I believe that any developer can learn to read closures. Many developers are using closures already without even knowing it. For example Javascript supports them and some Javascript libraries (e.g. jQuery) are full of code that utilizes closures.

michael said...

Great presentation.

I miss Closures every day, writing clunky code with anonymous inner classes, and fudges to get values out... It's all a bit wrong, and too big. Closures simplify code.

It's important to get the syntax right, and easy to read. But it's more important to get on with it. We've waited too long already for this.

Simon said...

I really find the FCM proposal syntax more natural and easy to read. When people decide which closures proposal they like, they don't necessarily completely decouple the syntax. I would love for a consensus to be reached and feel that the syntax is hampering BGGA as the strongest contender.

I'm not sure about Java as a lingua-franca. It seems a shame to pollute a real language with every conceivable idea. Could Java be a subset of something else?

josh said...

I've become a great fan of closures in JavaScript. They are just what the doctor ordered for doing event handling! I was ambivalent, or even mildly negative, about them before but I've changed my mind. By all means add them! (Supporting other languages more naturally would be a happy side-effect).

Max Kovalenko said...

Hi Neal, I just finished watching this presentation of yours: http://www.youtube.com/watch?v=0zVizaCOhME&feature=channel

You had an example like this one:
with(InputStream is: ...) {
// work with stream
}

"with" will call InputStream.close() for me. My question is what to do if close() throws an exception (reading from stream was fine, it's the close() that failed).
Usually you can't do much at this point and I prefer to catch IOException that close() might throw, log a warning and continue program execution.
I don't see how I could do it with this "with" closure example.

2nd question. You also mentioned that you might have 2 "with" chained (one for input and one of output stream for example) and a closure, and this will take care of closing both streams. If one of the close() throws an exception, I don't see how I could tell which one it was.

Any comments greatly appreciated!
Great talk by the way!

Neal Gafter said...

@Max: I too would expect the "with" method to propogate out any exceptions thrown by close().

If you care to intercept exceptions from one or the other with statement, you would not write the code in a way that doesn't allow you to intercept them separately. You'd put a try-catch between them.

Max Kovalenko said...

Big part of the closure elegance is going away however, and it won't look much different from the old-style code.

Old style:
InputStream is = ...;
try {
// do something
} finally {
try {
is.close();
} catch (IOException e) {
log.warn("Unable to close stream", e);
}
}

Closure style:
InputStream is = ...;
try {
with(is) {
// do something
}
} catch (IOException e) {
// problem here, I can't distinguish whether it's reading from stream, or close() that failed.
// I need another flag now
log.warn("Exception but not sure from what", e);
}

So it's really going to be like this:
InputStream is = ...;
boolean success = false;
try {
with(is) {
// do something
success = true;
}
} catch (IOException e) {
if (success) {
log.warn("Unable to close stream", e); // suppress exception from close()
} else {
throw e; // re-throw exceptions from read()
}
}

This is not elegant and not much different from the original code in terms of verbosity.

What's the right solution here?
Passing another optional closure that will be used by "with" for exception handling? Kinda ugly too.

Neal Gafter said...

@Max: Unlike the ARM proposal under consideration for project Coin, you don't have to use a single "with" form for all clients. You can use one that logs and swallows exceptions on close to use for input streams. In fact, I'd expect that to be provided in the JDK.

Max Kovalenko said...

Yep, you're right. All pieces are in place now.
Thanks!