Java Closures Prototype Feature-Complete
I'm pleased to announce that the Java Closures prototype now supports all of the features of its specification!
The complete source code, released under GPLv2, is in the project's openjdk repository. A binary build, suitable for use with an existing JDK6, is at http://www.javac.info/closures.tar.gz. Other related documents are on the website http://www.javac.info/
Although there is room for performance tuning, the prototype supports the full Closures (v0.5) specification. Based on your feedback, there are some changes in the prototype suitable for a future update of the specification:
- Renamed
Unreachable
toNothing
- Removed support for the type
null
- Overhauled restricted versus unrestricted
- Refined restrictions
- The variable is not the target of any assignment, or
- The variable is annotated @Shared
- Relaxed the closure conversion
for
-qualified method declarations- Added support for method references
- Implemented a classfile format for the
for
qualifier
We adopt the name used by Scala to represent the same concept.
We usednull
as a placeholder for an exception type when none can be thrown. The typeNothing
now serves that purpose;null
is no longer supported as the name of a type.
In the specification, an interface is considered restricted if it extends a marker interface. Unfortunately, the specification only provides a syntax for function type interfaces that are unrestricted. We modified the syntax so that a function type written using the=>
token designates a restricted function type, while one written using the newly introduced==>
token represents an unrestricted function type. This allows programmers to easily write APIs that restrict (or don't restrict) the operations of closure expressions passed as parameters.
We modified the distinction between restricted and unrestricted closures. As before, it is not legal to convert an unrestricted closure to a restricted interface type, nor is it legal tobreak
,continue
, orreturn
from inside a restricted closure to a target outside the closure. However, a restricted closure is allowed to refer to a non-final local variable from an enclosing scope. In this case a warning is given unless one of the following conditions holds:
It is possible to suppress the warning by annotating some enclosing construct
@SuppressWarnings("shared")
.
In response to user feedback, we've relaxed the relationship between a closure parameter's type and the target interface's parameter type. Rather than requiring them to be of the same type, they are now allowed to be related by an assignment conversion, including boxing or unboxing.
The for
keyword on a method declaration, meant to
introduce a control abstraction method that works like a loop, is now
treated syntactically like a modifier rather than appearing
immediately before the method name. This helps make the declaration
site more similar to the use site.
We added extensive support for treating a reference to a method as a closure using a newly introduced token
#
. The syntax is borrowed from the FCM proposal. The semantics are as follows:A method reference written as
Primary # Identifier ( TypeList )where the Primary designates an expression (as opposed to a type) is treated the same as a closure
or{ Type x0, Type x1 ... => tmp.Identifier(x0, x1 ...) }{ Type x0, Type x1 ... => tmp.Identifier(x0, x1 ...); }Where tmp is a temporary value that holds the computed value of the primary expression. The former translation is used when the resolved method has a non-void return type, while the latter is used when the resolved method has a void return type.
If the primary resolves to a type, then this is translated to
or{ Type x0, Type x1 ... => Primary.Identifier(x0, x1 ...) }{ Type x0, Type x1 ... => Primary.Identifier(x0, x1 ...); }when the resolved method is static, or
or{ Primary x, Type x0, Type x1 ... => x.Identifier(x0, x1 ...) }{ Primary x, Type x0, Type x1 ... => x.Identifier(x0, x1 ...); }when the resolved method is an instance method.
In addition, optional explicit type arguments, between angle brackets, may be placed immediately after the
#
token. These are used directly in the translated method invocation to resolve the method to be invoked.
We've impleemnted a class file representation of the for
qualifier to support separate compilation.