jstrachan | 27 Jan 06:05 2005

Re: [groovy-dev] Diff of Java and Groovy grammars

Martin C. Martin wrote:
> jastrachan@... wrote:
>> On 26 Jan 2005, at 15:08, Martin C. Martin wrote:
>>> This works well when the closure is used in one place, and executed 
>>> when it's defined, as above.  As a callback, though, it's less 
>>> clear.  If I use a closure as an actionPerformed callback, what would 
>>> a "return" statement return from?
>>  From a method, which invokes the closure (assuming its been developed 
>> to be able to handle such a thing). Clearly if you're using a closure 
>> as a method pointer (like a Java Bean listener method like Runnable or 
>> ActionListener, then it will have no effect).
>>>  If I write a function that takes a closure, I may not want the 
>>> closure to be able to exit my function, at least not without cleaning 
>>> up.
>> Its up to you to handle the request for a return however you want. You 
>> can use finally { } to clean up - or just gobble up the exceptions. So 
>> the caller of the closure is in full command over what to do. (We'll 
>> probably need two mechanisms to invoke closures, one in Groovy land 
>> that does all the exception handling for you, and one that just 
>> gobbles them up).
>>> For example, if I'm doing some numerical processing and with to find 
>>> an x such that f(x) = 0, I don't want f() to be able to exit from my 
>>> zero finder.
>> Sure - like I said its your call. However you may want to be able to 
>> abort a lengthy iteration by the closure deciding when to stop.
> Ah, but what should it return?

Its completely up to the author of the method/function to decide. You 
can also use the finally { } expression in Java/Groovy to explicity 
ensure that what you really really want returned, is always returned.

> In this example, it should probably return the best value so far.  But 
> the closure doesn't have access to the variables in the calling 
> function, but rather the defining function.  When both of those are the 
> same it's like a code block and there's no problem.  But when they're 
> different, well...

Note that the function is in complete control and can choose to return 
whatever it likes.

BTW another good example of return in a closure is iterating through a 
large table in SQL where the closure may decide its seen enough data for 
whatever reason - i.e. its a simple way to terminate some iteration that 
the function is in charge of.

>> doSomethingSlow(Closure c) {
>>   for (i in 0..someLargeNumber) {
>>      c.call(i)
>>   }
>> }
>> doSomethingSlow { i | if (i > 1000) { return } else { println i }}
> To be complete, what if it was:
> Double doSomethingSlow(Closure c) {
> ...
> }

The closure could supply the value to return

> So I'm coming around to the "closures as functions" thing. 

They are useful as functions for sure.