Friday, 28 December 2007

Java: The Closures Controversy

Joshua Bloch, one of the Principal Engineers at Google and author of the book Effective Java, gave a lecture that was published on recently about the forthcoming support for closures in Java.

Near the beginner of the lecture, Joshua explains how Java was designed from the ground up to be a practical language with a job to do rather than an academic exercise in language design and stresses that this remains an important goal for Java's evolution. In particular, he uses the phrase "Don't fix it until it chafes" to emphasize that a practical problem must be severe before changes to the Java language itself will even be considered.

The last major change to Java was generics, or parametric polymorphism as it is referred to in functional languages. Joshua states that Java is "not doing too well" in the face of the complexity that was introduced by generics, citing an example from Angelika Langer's 427-page Java generics FAQ.

In essence, Joshua explains why he thinks the proposed designs for Java's closures are too grand and should be reduced to only two special cases with absolutely minimal changes to the Java language. In particular, he gives the example of a trivial curry combinator written using the proposed style for Java's new closures:

static  { A1 => { A2 => R } } curry({ A1, A2 => R } fn) {
return { A1 a1 => { A2 a2 => fn.invoke(a1, a2) } };

For comparison, here is that function written in the statically-typed functional programming language OCaml:

let curry f a1 a2 = f(a1, a2)

Note the complete lack of types in the OCaml source code thanks to the language's powerful type inference.

Type inference is an essential component of statically-typed functional programming languages like OCaml, Haskell and F# and the lack of type inference in Java means that closures quickly become prohibitively complicated in all but the most trivial cases. Joshua's point is, quite correctly, that burdening Java with the complexity of full-blown closures when they are crippled by the absence of other language features is not constructive.

Joshua goes on to explain that closures are a general solution to some practically important problems in Java programming. Specifically, he cites fine-grained concurrency and resource management. The former refers to passing snippets of code to another thread for execution and the latter refers to using a combinator to encapsulate the undoing of state (e.g. closing a file handle)· He gives the following code as an example of this current deficiency in Java:

static void copy(String src, String dest) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int n;
while ((n = >= 0)
out.write(buf, 0, n);
} finally {

private static void closeIgnoringException(Closeable c) {
if (c != null) {
try { c.close(); } catch (IOException ex) { // ignore }

In the statically typed functional programming language F#, this is just:

let copy infile outfile =
use outstream = new StreamReader(File.OpenWrite outfile)
use instream = new StreamReader(File.OpenRead infile)
while not instream.EndOfStream do
instream.ReadByte() |> outstream.WriteByte

Note how F#'s use binding automates the closing of the stream at the end of its scope using .NET's uniform IDisposable interface.

Overall this lecture does a beautiful job of elucidating some simple practical problems that Java still struggles with. Joshua's concludes that the Java language should not be drastically altered but a new language should be created that addresses these problems. Joshua even cites the Scala programming language as one of the promising new languages for the JVM.

However, the Scala programming language is very much a research prototype and not a language for industry with a job to do. We were actually hoping that Joshua was going to announce a newer and more modern language for the JVM developed by Google that was designed and built for industrial use. Microsoft are already a long way down this road with their F# programming language and it seems a great shame that the Java platform remains so far behind. If Sun fixed some of the problems with the JVM itself, such as the lack of tail calls, and implemented a better language for the JVM we would surely be among the first adopters. Until then, we shall continue to use languages like OCaml and F# for our commercial work and not Java and the JVM.


Nicholas said...

I'm not much of a Java person, but I was shocked to find out that Java doesn't have this feature after so many years, and that it is being considered so heavily today. The reason is clear, C# has limited closures.

There was once a day when everyone used C++, but real progress on developing the language was slow. Along came Java which gave users a garbage collector and a VM. That changed the industry. Today, C# hasn't just copied Java, but they have closures and type inference (at least at some level.)

I think the Java community needs to realize they have an aggressive competitor that they must react to. This means adding new features to the language, as fast as the C# community is doing it. Otherwise Java will become the next C++ that everyone hates working in.

Neil Bartlett said...

"the Scala programming language is very much a research prototype and not a language for industry with a job to do"

In your opinion. There are many people who disagree and are indeed treating it as a language for industry. Certainly far more than would considering using Cafesterol, the OCaml to JVM bytecode compiler.

Flying Frog Consultancy Ltd. said...

Neil, have any of the people you believe are treating Scala as a language for industry shipped any product?