Tuesday, November 20, 2007

Closures Prototype Update and Extension Methods

Closures Prototype Update

The Closures for Java prototype now allows a closure to access mutated local variables from an enclosing scope. You can download the prototype here. You can also download the sources for the rewritten parts of Doug Lea's fork-join library, ported to use function types. It is a good example of how APIs can be affected by these language changes. Personally, I find the API simplifications to be quite compelling. If you're on the fence about function types, I recommend you have a look. Any feedback you may have is most welcome!

I mentioned previously that I'm working on a number of smaller language features, which hopefully will be considered for JDK7. For now, I'd like to talk about just one of them.

Extension Methods

Once an API has been published, you can't add methods to it without breaking backward compatibility. That's because implementations of the old version of the interface don't provide an implementation of any new methods. You can use abstract classes instead of interfaces, and only add concrete methods in the future. Unfortunately, that limits you to single inheritance.

One way API designers work around this limitation is to add new functionality to an interface by writing static utility functions. For example, java.util.Collection.sort acts as an extension of java.util.List. But such methods are less convenient to use, and code written using them is more difficult to read.

Extension methods enable programmers to provide additional methods that clients of an interface can elect use as if they are members of the interface. Todd Millstain's Expanders are the most full-featured version of this feature. The simplest version of this feature that I advocate would be to enable statically-imported methods to be used as if members of their first argument type. For example:

    import static java.util.Collections.sort;
    ...
    List<String> list = ...;
    list.sort();

Extension methods are completely orthogonal to closures, but they enable a number of typical functional-style programming patterns to be expressed more directly in Java using extension methods that accept closures.

Sunday, October 28, 2007

Java Closures: first prototype

I've finally had some time to make progress on a prototype of closures. If you want to see what an API looks like, you can compare Doug Lea's jsr166y fork-join framework to the same API ported to use the language features of the prototype.

If you want to try it, you can download an executable version of the prototype here. Make sure a JDK6 version of java and javac are on your path. This is binary-licensed under the JRL, but if a JSR is created I expect to license it under GPLv2. There are a few small test cases included.

This prototype supports

  • the BGGA function type syntax
  • closure literals
  • the closure conversion
  • the null type, disjunctive types, and exception transparency
  • definite assignment
  • Unreachable and completion transparency.
  • Catching multiple exceptions at once like catch(X1|X2 ex) { ...
    [not closely related to closures but the implementation was simple once closures are there]

This prototype does not yet support

  • a closure using a mutated variable from the enclosing scope
  • nonlocal control-flow (break, return, and continue)
  • the control invocation statement and loop abstractions

I'm intentionally distributing it before these features are available. The idea is that people can try this version, and compare it to the next version with these features working.

Separately, I'm working on a set of smaller language extensions for JDK7, some of which interact very nicely with Closures. For example, "extension methods" enable you to have the effect of adding methods to existing interfaces (e.g. adding "each", "filter", etc to Collection) without breaking backward compatibility. I'll write more about these over the next few days.

This is still rough around the edges, but any feedback you have is most welcome.