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!