Tuesday, 10 April 2007

ASF open letter to Sun

Despite a great deal of behind the scenes effort, the Apache Software Foundation (ASF) has been forced to write an open letter to Sun Microsystems. This letter is regarding the inability of the ASF to obtain a version of the testing compatibility kit for Java SE, as needed by Apache Harmony, under a suitable license.

As the open letter details, Sun is attempting to avoid its contractual obligations from the JSPA, which is the legal agreement of the Java Community Process (JCP). This seriously places at risk the ability of the JCP to act as a truly independent open standards organisation.

Considerable efforts (over 7 months) have gone into trying to avoid reaching this point. It is hoped that now the issue is public, the Java community can bring to bear pressure on Sun to meet its contractual obligations quickly and amicably.

Further questions may be answered in the FAQ.

On this issue, Geir Magnussen Jr acts as the official ASF representative. I am speaking here simply to provide information.

Java Control Abstraction for First-Class Methods (Closures)

Stefan Schulz, Ricky Clarkson and I are pleased to announce the release of Java Control Abstraction (JCA). This is a position paper explaining how we envisage the First-Class Methods (FCM) closures proposal being extended to cover control abstraction.

Java Control Abstraction

So, what is control abstraction? And how does it relate to FCM? Well its all about being able to add methods in an API that can appear as though they are part of the language. The classic example is iteration over a map. Here is the code we write today:

  Map<Long,Person> map = ...;
  for (Map.Entry<Long, Person> entry : map) {
    Long id = entry.getKey();
    Person p = entry.getValue();
    // some operations
  }

and here is what the code looks like with control abstraction:

  Map<Long,Person> map = ...;
  for eachEntry(Long id, Person p : map) {
    // some operations
  }

The identfier eachEntry is a special method implemented elsewhere (and statically imported):

  public static <K, V> void eachEntry(for #(void(K, V)) block : Map<K, V> map) {
    for (Map.Entry<K, V> entry : map.entrySet()) {
      block.invoke(entry.getKey(), entry.getValue());
    }
  }

As can be seen, the API method above has a few unique features. Firstly, it has two halves separated by a colon. The first part consists of a method type which represents the code to be executed (the closure). The second part consists of any other parameters. As shown, the closure block is invoked in the same way as FCM.

The allowed syntax that the developer may enter in the block is not governed by the rules of FCM. Instead, the developer may use return, continue, break and exceptions and they will 'just work'. Thus in JCA, return will return from the enclosing method, not back into the closure. This is the opposite to FCM. This behaviour is required as the JCA block has to act like a built-in keyword.

One downside of the approach is that things can go wrong because the API writer has access to a variable that represents the closure. The API writer could store this in a variable and invoke it at a later time after the enclosing method is complete. However, if this occurred, then any return/continue/break statements would no longer operate correctly as the original enclosing method would no longer be on the call stack and a weird and unexpected exception will be thrown.

The semantics of a pure FCM method invocation are always safe, and there is no way to get one of these unexpected exceptions. But, for JCA control abstraction we could find no viable way to stop the weird exceptions. Instead, we have chosen to specifically separate the syntax of FCM from the syntax of control abstraction in JCA.

Our approach is to accompany the integration of control abstraction into Java by a strong set of messages. Developers will be encouraged to use both FCM callbacks and JCA control abstractions. However, developers would only be encouraged to write FCM style APIs, and not JCA.

Writing the API part of any control abstraction (including JCA) is difficult to get right (or more accurately easy to get wrong). As a result, some coding shops may choose to ban the writing of control abstraction APIs, but by having a separate syntax this will be easy to do for the tools. It is expected, of course, that the majority of the key control abstractions will be provided by the JDK, where experts will ensure that the control abstraction APIs work correctly.

Summary

This document has taken a while to produce, especially by comparison with FCM. In the end this indicated to us that writing a control abstraction is probably going to be a little tricky irrespective of what choices the language designer makes. By separating the syntax and semantics from FCM we have clearly identified the control abstraction issue in isolation, which can only be a good thing.

Feedback always welcome!

Wednesday, 4 April 2007

First-Class Methods: Java-style closures - v0.5

Stefan and I are pleased to announce the release of v0.5 of the First-class Methods: Java-style closures proposal.

Changes

Since v0.4, we have focussed on understanding the relationship between the various use cases for closures and FCM. We identified the following three use case groups:

  • Asynchronous - callbacks, like swing event listeners - where the block is invoked by a method other than the higher order method to which it was passed
  • Synchronous - inline callbacks, like list sorting, filtering and searching - where the block is invoked by the higher order method and completes before it returns
  • Control abstraction - keywords, like looping around a map, or resource acquisition

Having identified the three groups, we found that we could extend FCM from asynchronous to synchronous with a couple of simple changes. But we became convinced that the control abstraction use case is completely different. This is because the meaning of return, continue and break needs to be entirely different in the control abstraction use case.

As a result, of our deliberations, these are the main changes from v0.4:

1) Local variables can now be accessed read/write by all FCM inner methods. This enables the synchronous closure use case, and does not greatly compromise the asynchronous use case. We were concerned about the possibility of race conditions, but we identified that this is caused by concurrent access to the local variable, and could be addressed by a warning annotation - @ConcurrentLocalVariableAccess:

  public void addUpdater(@ConcurrentLocalVariableAccess #(void()) updater) {
    // invoke updater on a new thread
    // marked with annotation as local variable could be accessed
    // by new thread and original at the same time
  }

  public void process() {
    int val = 6;
    addUpdater(#{
      int calc = val;    // OK, can read local variables
      val = 7;           // OK, can update local variables
    });
    System.out.println(val);  // race condition - warning from annotation
  }

2) Added brief section on transparency. When considering synchronous closures it is desirable to not have to be concerned with every checked exception. Although we discussed alternatives, we simply reference the BGGA work here.

3) Removed the creation of stub methods for named inner methods. This prevents FCM from creating MouseListener instances, but is safer. As a result, we also removed the method compound concept.

Summary

This version tidies up the princpal loose ends of FCM and provides rationale for our decisions. We think it represents a simple and safe extension to Java which would be of great value to developers. It should also be noted that we are not intending to extend FCM further to cover the control abstraction use case.

If you've any more feedback, please let us know!