hlovatt schrieb:
> 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).
sorry for warming up this thread after a week...
It is a shame that I not yet had a chance of reading this... but maybe
you can answer some questions.
For example how did he define exit point? for example in this case
def foo() { throw new RuntimeException("something") }
while (true) {
foo()
}
you said "end of block", so I guess it has only one exit point... or
does the foo() method have two then? If yes, wouldn't mean that
exceptions are bad in Tennent's Correspondence Principle?
But ok, let us say this has only one exit point.... Now, if we have a
list and we want to proceed all elements until we meet a certain element
and then stop processing, then I would write something like this:
for (XY element : list) {
if (element==myBreakCondition) break
doSometing(element)
}
this has (at last) two exit point because of the loop, so I guess I
would have to change the loop condition to do the additional check
XY element
for (Iterator it=list.iterator();
it.hasNext() && element!=myBreakCondition;) {
element = it.next()
doSomething(element)
}
but in case of a "closure" I could do this:
list.each { XY element, LoopFlow flowControl ->
flowControl.breakIf(element==myBreakCondition)
doSometing(element)
}
where flowControl.breakIf would throw an exception, each (I will call
each an iteration method, because it iterates over the list here) would
catch that exception and use flowControl to check the exception... Would
this still fulfill the "only one exit point per block" idea?
Or the next question... if we say that a "closure syntax" overlaps with
the syntax generally used by blocks, but if the "closure" is no block...
does the principle then still apply to break/continue which have to be
applied to the iteration method?
Or let us say a break statement is not allowed in a "closure".. what
does the principle say to this? I mean having one exit point per block
is easily fulfilled with that, because it would not compile... Is the
language to be considered as "less expressive" then, even if the break
statement can be expressed by other elements that are not of syntactic
nature? Or if I had a different syntactic element to do a break in a
closure.. would the language then still be considered as "less powerful"?
[...]
> 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.
on the other hand.... why is that a illegal usage of "break iLoop"? I
mean ok, invokeLater might execute the "closure" in a different Thread,
but what if not?
I guess that's why the closure proposal expects the usage of "for" here:
l1: while (true) {
l2: for each(element:list) {
if (element == myBreakCondition) break l1
break l2
}
}
from a pragmatic point of view I guess you would have to tell your
iteration method that it needs to respond to "break l2", but not to
"break l1". But of course I can not write:
void for each(List list, MyClosure closure, Label label) {
label: for (x : list) closure.call()
}
and you can get even more fun with something like:
l1: while (true) {
l2: for each(element:list) {
check (element == myBreakCondition, {break l1})
break l2
}
}
which means that check should execute the closure {break l1} if
element==myBreakCondition. If we use the interface coercion that was
proposed, then we would have to throw an compile time error here if the
interface (for example Runnable) does not throw that exception. Or not?
I mean according to your text above it must, because Runnable does not
throw that exception and check would have to throw that exception too.
But the advantage of the "for" keyword usage seems to be kind of lost here.
So from looking at this from the perspective of a static type system
where I want to have compile time checks as much as possible a checked
exception would make sense to me. From the perspective of a API writer I
get horrified but that ideas, because it means any method that somehow
has to handle "closures" containing a break/continue would have to throw
the exception. It would be equally annoying to he RemoteException for
example. On the bytecode level it makes no difference, because the JVM
is not checking if a exception is checked or not, only the Java compiler
does.
Regardless if new exception type is defined or not, I guess the API
writers still get exposed to an implementation detail if they want to
have their custom iteration methods which I think is bad...
And even if there is a way to express the each without letting it
explicitly catch and evaluate the exception (I would really like to know
how to get around that), a checked exception would still mean, that at
some point any API writer gets exposed to this implementation detail
when they use the iteration method on their own.
> 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)?
so you have no problem with break, but with return? I hope my check
method example above did show you that it is not only "return", it is
also break/continue to some extend.
bye blackdrag
--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---