On Oct 21, 12:40 pm, "Neal Gafter" <[EMAIL PROTECTED]> wrote:
> A new exception hierarchy outside Throwable is necessary for closures to
> satisfy Tennent's Correspondence Principle, which as you know is a powerful
> litmus test for the expressive power of a language feature such as closures.
Tennent used his Principle of Correspondence to argue against return,
break, and continue and instead advocated that every block should have
one exit point (end of block). His argument in Javanese is:
// Start with this block - the block is between the braces
int i = 0;
while ( true ) {
if ( i > 3 ) break;
out.println( i );
}
Then wrap the block in another block:
// Using Correspondence it should be the same - but it isn't
int i = 0;
while ( true ) {
while ( true ) {
if ( i > 3 ) break;
out.println( i );
}
}
Oops meaning of block changed, contrast this with:
int i = 0;
while ( true ) {
if ( i <= 3 ) out.println( i );
}
Then wrap the block in another loop - the block now has the same
result:
int i = 0;
while ( true ) {
while ( true ) {
if ( i <= 3 ) out.println( i );
}
}
Therefore using Correspondence as an argument for a JVM extension to
support return etc. from within closures is weak, since Tennent
argued, using his own principle, that the correct answer is not to
have return etc.
A compromise position is to allow return etc. but require them to name
the block they are returning from (like break and continue currently
do but also extend the naming to include method names). Then at least
the action of the block is clearly flagged, e.g.:
int i = 0;
iLoop: while ( true ) {
while ( true ) {
if ( i > 3 ) break iLoop; // still works as expected
out.println( i );
}
}
Having said that the block must be named, then the standard exception
mechanism can be used and this has the added advantage of providing a
compile time check for asynchronous use cases, e.g.:
// in the example below method { .. } is suggested short syntax for an
inner class (closure)
int i = 0;
iLoop: while ( true ) {
invokeLater( method { ...; break iLoop; ... } ); // Error since
invokeLater doesn't catch iLoopBreakException
}
}
The above example is caught at compile time because when expanded the
object passed to invokeLater throws a checked exception, iLoopBreak,
which isn't caught (and can't be caught because it is a local class)
by invokeLater. See previous return example for how break etc. are
expanded.
I would also caution that adding support for non-local returns will
probably not be worth the trouble, since I doubt that non-local
returns will be used much. For example, what is a good use case
(remember that many languages don't have return etc. at all)? A second
question, how often do you use a named break or continue? You can
always add features but a more pertinent question is whether a feature
is worth adding, not whether it is technically feasible to add. There
is a ledger here, you need to account cost of addition against
usefulness.
NOTE: There is a typo in my original post, exception Jump is meant to
extend Exception not RuntimeException, IE it is meant to be a checked
exception so that asynchronous use cases are caught at compile time.
Also note that the exception, ExampleReturn, is an inner class and
therefore private to the method, example, in which the inner class
(closure) is declared in and therefore cannot be caught by anything
else (except for catching Jump which like Error it is suggested that
you don't do).
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JVM
Languages" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/jvm-languages?hl=en
-~----------~----~----~----~------~----~------~--~---