First-Class Methods: Java-style closures

Our aim when writing this proposal was to provide developers with much of the power of full-blown closures, but without the complexity. The syntax had to fit neatly within Java, but more importantly so did the semantics. The result of our work is a closure proposal that focuses on methods rather than closures, hence the name 'First-class methods'.

For those currently programming in Java, the method is the principal construct where application logic resides. Our proposal simply takes methods and allows them to be used as first-class objects within the application. But the new constructs are still recognisably methods. This results in a rapid learning curve - since all developers are already familiar with methods.

The proposal adds four new syntax elements:

Method literals - a type-safe way to refer to a method

Method types - a way to define the parameters and result of a method

Invocable method references - a reference to a method-object combination that together can be invoked

Inner methods - a way to write a method inline within another method, similar to inner classes

The inner method version will compile to almost exactly the same bytecode as the inner class version. But the syntax is much shorter and the semantics clearer.

Relationship to other proposals

There are two other closure proposals being debated.
The CICE proposal aims to simplify inner class creation, while the BGGA proposal aims to introduce full-blown closures and API driven control flow statements.

The First-Class Methods (FCM) proposal is located between CICE and BGGA.
FCM is considerably more powerful than CICE, which is still lumbered with the dreaded OuterClass.this syntax of the inner class. Equally, FCM doesn't get caught up in the obsessive BGGA requirement of Tennent's Correspondence Principles with its myriad of nasty implications (such as last-line-no-semicolon-return, exceptions for control-flow and RestrictedFunction).
Instead FCM focuses on empowering the humble, but familiar, method.

Summary

The First-Class Methods proposal (FCM) proposal provides an alternative to the two existing closure proposals.
It focusses on the familiar concept of methods, providing all the syntax and semantics necessary to use them to their full potential.
The result is a proposal that gives the developer power without complexity or surprise and would make a great Java language change.

As always, Stefan and I would love to hear your feedback on this proposal.

List literals

This syntax is pretty clear and simple, creating an ArrayList (no opportunity to create a LinkedList etc.). The problems occur when you start considering the complications of generics.

The simple case is assignment, as shown above.
Here, the generic type of the RHS would be inferred from the LHS without difficulty.
However, if the literal isn't assigned to a variable then its a lot more complex.

Here, the this->processTask() syntax is being automatically adapted to the required Runnable interface. But often, we don't want to create a separate method for this, so lets create the method anonymously:

public void init() {
executor.execute(Runnable->run() {
// code of anonymous method to run in the executor
});
}

This would operate in the same way as an inner class, except with one method. In other words, the contents of the anonymous method has the same rules and restrictions as a method does when written within the normal inner class syntax. Hence, 'return' will return from the anonymous method, not the surrounding init() method. Thus, the above is merely a exact shorthand for:

Compared to BGGA

Firstly, it is less of a jump for existing Java programmers.
This is simply a slightly shorter syntax for creating an inner class.
I suspect many Java developers will appreciate that.
This change also works well together with method adaptation, which provides an alternative way to refactor the common case of the single line inner class that calls another method.

Secondly, it is fully and clearly documentable.
The parameter being passed to the executor or the sort method is a real interface, which can be documented in all the detail needed.
Documenting a BGGA closure method will have to be done for every definition.

Thirdly, there is no confusion over different syntaxes depending on whether its a synchronous or asynchronous use-case. There is no need for a hacky RestrictedClosure interface.

Finally, it feels more correct to be passing an object, rather than an arbitrary block of code, to a method that processes it at some later point in time. An object is expected to have its own lifecycle - whereas a developer expects a block of code to be executed immediately.

However, there are downsides too.
Firstly, anonymous methods are less powerful. There is no ability to have function types, and the functional programming styles that accompany them.

Secondly, anonymous methods are more verbose.
The BGGA proposal presents examples that are extremely short and pithy, including for executors. Except of course that the rules for what code you can put in that block differ from other blocks.

Finally, the synchronous use cases are not served that well by anonymous methods.
The control statement form of BGGA is very expressive of the intent of the coder in those cases (for example looping around a map, locking or working with files).

Summary

What is my opinion? Well I haven't quite made up my mind yet.
I should be a natural supporter of BGGA, as I am in favour of pushing Java forward.
But BGGA bothers me in lots of annoying little ways.

So, consider my blogs on anonymous methods and method adaption as my attempt to explore an alternative to BGGA. Comments welcome as always.

Tuesday, 6 February 2007

BGGA Closures has been following one course to address the verbosity of defining an inner class in Java. In this blog I want to consider an alternative that could be more useful in some circumstances.

Method adaption

Consider a long running task that will use the Java 5 executor framework (I could also have used a swing example):

public void init() {
executor.execute(
new Runnable() {
public void run() {
// lots of code to run in the executor
}
}
);
}

The problem is that frequently, the code to be run gets quite long.
So, what may happen is that the code is refactored.
One refactoring is to use top-level classes, but lets consider the simpler alternative - method refactoring:

However, the developer is really having to do a lot of tedious drudgery to achieve the goal here. Could it be simplified? Perhaps we could use method literals:

public void init() {
executor.execute(this->processTask());
}
private void processTask() {
// lots of code to run in the executor
}

So, two things have happened here.
Firstly, a method literal has been used - this->processTask().
This represents the processTask() method on this specific object.

The second thing that has happened is that an adaptor has been generated for us.
This is a new class that implements Runnable, and calls processTask() from the run() method exactly as we would have if we coded it ourselves.

Obviously, there is a restriction that the method signature of processTask() must match the method signature of Runnable.run(). But that seems perfectly reasonable.

My one reservation is whether too much information has been lost with this. (The choice of Runnable is being inferred in the example.)
One variation is to explicitly specify the API and method that is to be adapted to:

Here in this variation, the 'cast' is specifying the method signature to be adapted to, again using a method literal (this time not tied to a specific instance).
This is a more general syntax, as it also allows assignment to a variable:

The advantage of this variation is that it handles cases like MouseListener where there are many possible methods to adapt to.
This disadvantage is that there is more code which could be inferred.

But which of the two variations works best? Or perhaps the first is just a special case of the second? And is a 'cast' the appropriate syntax here?

Summary

Method adaption could be a useful language change.
It certainly doesn't compete with BGGA closures for raw power, but it does provide an alternative for many async use cases that could be viewed as being a lot clearer.

As always, please view this as a concept for discussion (and its certainly not a new idea)
I've not proven it can be implemented, but there's nothing obvious hitting me yet.
As such, all opinions are welcome...

At this point our nice switch statement silently continues without doing anything.
Which probably isn't what we want.
So, we would need to search our entire application to find switch statements referencing Colour and update them.

So, could we do better?
Well, what if we could mark the switch statement as 'must contain all the values of the enum':

Now, with the new annotation, this piece of code won't compile (as BLACK isn't handled).
We would need to either add a case for BLACK, or a default clause.

Using an annotation here seems appropriate.
It doesn't affect the bytecode, but does validate it.
In other words, its very similar to @Override.

There is a downside to the annotation approach - its compile time only.
If BLACK is added to the enum without recompiling the switch statement, then there will be no error either at compile time or runtime.
But this seems a reasonable balance for the feature.

There's another problem though - an annotation can't be added at this point in the code at present.
However, JSR 308 is working on this right now, so hopefully this restriction will disappear.

Moving beyond @CompleteEnumSwitch, I could also envisage an @NoFallThroughSwitch which would make falling through not compile in switch statements.

Any thoughts on this concept?

BTW, thanks to Ricky Clarkson for talking about complete switches which triggered me to write this.