External References: Closures for Java (CfJ) version 0.6 part b
Neal Gafter
neal at gafter.com
Sat Feb 27 07:09:27 PST 2010
Alex Buckley asked me to include BGGA and other documents in messages on
this list, so that they may formally be considered contributions to project
lambda.
Enclosed please find the Closure for Java specification, version 0.6, part
b. It can also be found at <http://www.javac.info/closures-v06b.html>.
Closures for Java (v0.6b)
*Neal Gafter and Peter von der Ahé*
Building on *lambda expressions* and *exception type parameters* described
in the companion document v0.6a, we describe support for *control
abstractions*, which are APIs that can abstract patterns of control. These
correspond to *blocks* and *lambda expressions * in languages such as Ruby,
Smalltalk, and Scala.
Block Expressions
We extend the syntax of a parenthesized expression to allow it to be
preceded by a sequence of statements. The grammar for a parenthesized
expression [JLS
15.8.5<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.8.5>]
is changed to:
ParExpression:*(* *BlockStatementsopt* *Expression* *)*
Note that the existing syntax for a parenthesized expression is a special
case of this.
*Meaning of Expressions*: The specification for a parenthesized expression
is modified to describe its new execution semantics: The block statements
(if any) are executed in sequence, from left to right. The result of the
block expression is:
- The type Nothing if there are block statements and the last block
statement cannot complete normally; otherwise
- The value and type of the final expression
*Definite Assignment*: The definite assignment rules for this construct are
almost identical to that for the block statement. The definite assignment
state before the first block statement is the definite assignment state
before the parenthesized expression. The definite assignment state before
the subexpression is the definite assignment state following the last block
statement. The definite assignment state after the parenthesized expression
is the definite assignment state after the contained expression.
*Exception Checking*: A parenthesized expression can throw exception type E
if any statement or expression immediately contained in it can throw E.
*Scoping*: Local variables and classes declared by an immediately contained
statement is in scope until the end of the parenthesized expression.
Control invocation syntax
A new invocation statement syntax is added to make closures convenient for
control abstraction:
*ControlInvocationStatement*:for*opt Primary* (* FormalParameters *: *
ExpressionListopt* ) *Statement*
for*opt Primary* (* ExpressionListopt* ) *Statement*
This syntax is a shorthand for the following statement:
*Primary* *(* *ExpressionList*, *# (* *FormalParametersopt* *) (* *Statement
* *(Void)null ) ); *
(See the later section *loop abstractions* for the meaning of the optional
for keyword) This syntax makes some kinds of function-receiving APIs more
convenient to use to compose statements.
We could use the shorthand to write our previous example (0.6a) this way
withLock(lock) {
System.out.println("hello");
}
Another example of its use would be a an API that closes a
java.io.Closeableafter a user-supplied block of code, discarding any
exception from
Closeable.close:
<R, T extends java.io.Closeable, throws E>
R with(T t, #R(T) throws E block) throws E {
try {
return block.invoke(t);
} finally {
try { t.close(); } catch (IOException ex) {}
}
}
We could use the shorthand with this API to close a number of streams at the
end of a block of code:
with(FileReader in : makeReader()) with(FileWriter out : makeWriter()) {
// code using in and out
}
Loop Abstractions
The specification supports writing methods that act as control statements,
but when used to support loops the API implementor should be able to specify
that the controlled statement should capture the meaning of break and
continue in a way analogous to the built-in loop statements. For this
purpose we allow the for keyword at the beginning of a control invocation
statement (see above), and introduce the use of the keyword for as a
modifier on method declarations:
*MethodDeclarator*:for*opt* *Identifier* ( *FormalParamterListopt* )
An overriding or implementing method must be declared with the keyword
forif and only if the method being overridden or implemented was
declared with
the keyword for.
A control invocation statement must use the for keyword if and only if the
method being invoked was declared with the keyword for.
Within the controlled statement of a control invocation statement using the
keyword for:
- An unlabelled break statement breaks from the control invocation
statement.
- An unlabelled continue statement breaks from the controlled statement.
*Example*: The following illustrates a method used to loop through the
key-value pairs in a map. The method
<K,V,throws X>
void for eachEntry(Map<K,V> map, #void(K,V) throws X} block)
throws X {
for (Map.Entry<K,V> entry : map.entrySet()) {
block.invoke(entry.getKey(), entry.getValue());
}
}
allows us to rewrite this
void test(Map<String,Integer> map) {
for (Map.Entry<String,Integer> entry : map.entrySet()) {
String name = entry.getKey();
Integer value = entry.getValue();
if ("end".equals(name)) break;
if (name.startsWith("com.sun.")) continue;
System.out.println(name + ":" + value);
}
}
like this
void test(Map<String,Integer> map) {
for eachEntry(String name, Integer value : map) {
if ("end".equals(name)) break;
if (name.startsWith("com.sun.")) continue;
System.out.println(name + ":" + value);
}
}
Unmatched Control Transfers
Control transfers by return, break, or continue can, within an expression
lambda, jump to a target outside the body of the lambda. It is possible for
such code to be invoked at a time that the target of the transfer is not on
the call stack of the current thread. In this case an exception of type
UnmatchedTransferException is thrown.
package java.lang;
/**
* Exception thrown when a transfer from within a lambda doesn't have
* a matching frame on the stack of the current thread.
*
* @author gafter
*/
public class UnmatchedTransferException extends RuntimeException {
/**
* This constructor is used by compiler-generated code.
*/
public UnmatchedTransferException(Jump jump);
/**
* Returns the thread in which the transfer target is executing.
*/
public Thread thread();
/**
* Return the exception to be thrown to cause the transfer to
* occur. This can be used to implement concurrent APIs
* that support control transfers. See, for example,
* http://gafter.blogspot.com/2006/10/concurrent-loops-using-java-closures.html
* and http://markmahieu.blogspot.com/2008/08/for-eachconcurrently.html
*/
public RuntimeException transfer();
}
Acknowledgments
The authors would like to thank the following people whose discussions and
insight have helped us craft, refine, and improve this proposal:
* C. Scott Ananian, Lars Bak, Cedric Beust, Joshua Bloch, Gilad Bracha,
Martin Buchholz, Alex Buckley, Maurizio Cimadamore, Ricky Clarkson, Stephen
Colebourne, Danny Coward, Luc Duponcheel, Erik Ernst, Rémi Forax, James
Gosling, Christian Plesner Hansen, Cay Horstmann, Kohsuke Kawaguchi, Danny
Lagrouw, Doug Lea, Peter Levart, "crazy" Bob Lee, Mark Mahieu, Niklas
Matthies, Tony Morris, Martin Odersky, Terence Parr, Tim Peierls, Cris
Perdue, John Rose, Ken Russell, Stefan Schulz, Guy Steele, Mads Torgersen,
Zdenek Tronicek, Jan Vitek, *and* Dave Yost. *
Changes in this revision (0.6) compared to BGGA 0.5
- The translation of the control invocation statement has been modified
to reflect changes in the lambda syntax.
- UnmatchedNonlocalTransfer has been renamed UnmatchedTransferException.
Changes that need to go into the prototype
- Implement block expressions.
- Revise the implementation of the control invocation statement as
specified.
- Implement complete transparency for control flow from a closure.
Specifically, it should not be possible to intercept matched control
transfers by catching Throwable.
------------------------------
[image: Creative Commons
License]<http://creativecommons.org/licenses/by-sa/3.0/us/>
Closures for Java by Neal Gafter and Peter von der
Ahé<http://www.javac.info/>is licensed under a Creative
Commons Attribution-Share Alike 3.0 United States
License<http://creativecommons.org/licenses/by-sa/3.0/us/>.
More information about the lambda-dev
mailing list