Tuesday, October 30, 2007

Java Closures: A Quick Look


Neal Gafter is back! And he has brought treats for Halloween by way of a prototype on the closure proposal.

Essentially, it's a binary version of a modified JDK 6, released under the Java Research License. If Java is our home, Neal is building a whole new section, with a deck and swimming pool.

As a first exercise, I have converted my modest Groovy jar searcher into pure closure-Java. While doing the research, I realized:

  • Syntax is like construction. You can watch both all day but it's when you get your hands dirty and pick up a tool, that things begin to click.
  • Much like generics, closures will bring a lot of new terms and concepts. I don't mean the notion of a closure, per se, but rather the implementation in Java.
  • Already there is a lot of discussion: most of it from hardcore syntax surfers who revel in the corner cases and possibilities. (And more power to 'em)
The upshot is: I wonder if there is an opening in the blogtomonous collective for a gentler introduction. Even easier (and quicker) than the Groovy example mentioned above.

Here's a quick look....

The Setup
  • The download is available via Neal's original post Be sure to read the JRL
  • If you're on Windows, you might want a tool like 7-Zip to open the ztar file
  • Define CLOSURES to be the main directory
  • Ensure that JDK 6 is in the path. The shell files in CLOSURES/bin are key, as they modify boot classpath to use the new stuff. Though I love Bash on Windows, I used straight Windows BAT files that were morphed from javac and java in ~/bin.
The Gist

I'll assume that you're familiar with closures from Groovy, Ruby, Scheme, etc. With respect to the Java syntax, the most important things to understand are the Closure Literal and the Function Type.

In essence, the Closure Literal is the closure body; a Function Type is an abstract data type, a generalization of the venerable T for Generics. The difference is that the Function Type specifies many types for a function: (1) the types of the parameters, (2) the return type, and (3) possible exceptions.

I know: ZZZzzzz. To the ExampleCave, Batman!


// SNIP: public static void main...

String bulletin = " Hello Closure! ";

// Below, think: Type varName = closure;
//
// where Type = Function Type = { String, String => String }
// varName = myEasyClosure
// closure = Closure Literal (i.e. _the_ closure)

{ String, String => String } myEasyClosure =
{ String a, String b => a + bulletin + b };

// The closure is built into a class with an invoke method.
// To use it, simply call invoke with appropriate parameters.

String s = "this ";
String t = " is cool";

String result = myEasyClosure.invoke( s, t );

// output:
this Hello Closure! is cool

As annotated above:
  • We have a closure called myEasyClosure
  • Just as a generic type gives us, well, the type of a generic class, the Function Type states the types of the entire closure. Gafter could ask to us write IT_TAKES_2_STRINGS_AND_RETURNS_A_STRING but mercifully we write { String, String => String }. It is vital to understand that syntax.
  • The Closure Literal echoes the syntax of the Function Type: { params => expression }. Note that it doesn't return anything.
  • The whole point of closures are free lexical bindings: e.g. the free bulletin variable. Though this example is silly, that's where things get cool.
Keen readers will note that Function Types also specify exceptions. Let's decide that our closure should check for null on the parameters, and throw an IllegalArgumentException if that contract is violated.

Here's how to express it:


// remember:
// FunctionType varName = closure;

{ String, String => String throws IllegalArgumentException }
myEasyClosure =
{
String a, String b =>

if( a == null || b == null ) {
throw new IllegalArgumentException
("null parameters not allowed");
}

a + bulletin + b // no return or semi-colon !
};
Two points here:
  • The Function Type looks complicated, but we simply added a throws IllegalArgumentException into the definition.
  • In both examples, note that the final part of the closure body is an expression.
That's it... It should be fairly easy to mock up these examples with the prototype. With that foothold, it is easier to understand the more complex examples and discussions.

2 comments:

JP said...

Michael,

Good additional points added further to Neal's explanation.

Thanks
Prashant
http://prashantjalasutram.blogspot.com/

rhyolight said...

AWESOME! I can't wait until this officially gets into java.... and my work environment adopts the new version... so about 4 years.... at which time I'll hopefully be developing in Ruby or Groovy.

Nevermind.