jastrachan | 28 Jan 19:05 2005
Picon

Re: [groovy-dev] Closure control flow

On 28 Jan 2005, at 03:14, cpoirier@... wrote:
> Hi Mike,
>
> Let me preface this by saying I respect you and your opinions, and 
> generally
> agree with most of what you say.  However . . .
>
> Quoting Mike Spille <mike@...>:
>
>> Note that Java and Classic Groovy blocks do not yield a value - there 
>> is no
>> "value of a block". This is a huge change.  And hugely ambiguous, as 
>> the
>> 'b' example above shows - is b a closure or an int?
> [...]
>> This is fundamentally changing what a "block" means in Groovy, it's an
>> attempt to unify closures and blocks.  Which I think is highly 
>> un-groovy.
>
> You are wrong.  ;-)
>
> Java blocks cannot be passed around.  Period.  So once we start 
> changing that,
> there is no good reason not to pursue the change to its logical end.
>
> Closures in Ruby (for instance) are useful /because/ they behave just 
> like
> blocks -- they allow the user to define their own control structures.  
> "while"
> doesn't do quite what you'd like?  Roll your own.  That is the point of
> closures.
>
> You have repeatedly said that Groovy Classic blocks don't return a 
> value.  Yes
> they do, in most cases.  The problem has been that a flaw in the 
> grammar meant
> that you could assign a block directly to a variable without an 
> intervening
> blessing (ie. lambda).  This is one of the core reasons Groovy 
> Classic's
> grammar is irreparably broken.  I just hope TeamNewGroovy fix it.
>
> When you see the following Java code:
>
>    try {
>       for( element : myList ) {
>          if( element.doSomething() )  {
>             return;
>          }
>       }
>    }
>    catch( Exception e ) {
>       panic();
>    }
>
> I have no doubt that you expect that return to jump out of its block 
> and
> terminate the context method.  I further have no doubt that you expect 
> that
> return to never be executed if an exception is thrown before finding 
> an element
> whose doSomething() returns true.
>
> Now, let's change it to the Groovy version:
>
>    try {
>       myList.each { element |
>          if( element.doSomething() )  {
>             return;
>          }
>       }
>    }
>    catch( Exception e ) {
>       panic();
>    }

Fantastic example Chris! I think this illustrates the point superbly 
well. Closures when used well should just become similar to regular 
control flow operations, but allowing smarter methods (like this each() 
method) taking more of the load on complexity/resource management.

Also note that, from an implementation perspective, the return is local 
to the method creating the closure, so its easy to generate bytecode to 
automatically wrap the each() method call to do the right thing to 
catch the 'return' exception - the each() method is unaware of the 
return, its just like any other runtime exception which could happen, 
like a NullPointerException inside the closure code, which all good 
iteration method implementations are meant to handle nicely & close 
things down safely, just like GroovySQL does with JDBC resources.

James
-------
http://radio.weblogs.com/0112098/


Gmane