Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one return from a groovy closure and stop its execution?

I would like to return from a closure, like one would if using a break statement in a loop.

For example:

largeListOfElements.each{ element->     if(element == specificElement){         // do some work                   return // but this will only leave this iteration and start the next      } } 

In the above if statement I would like to stop iterating through the list and leave the closure to avoid unnecessary iterations.

I've seen a solution where an exception is thrown within the closure and caught outside, but I'm not too fond of that solution.

Are there any solutions to this, other than changing the code to avoid this kind of algorithm?

like image 503
Craig Avatar asked Apr 19 '09 15:04

Craig


People also ask

How do closures work in Groovy?

A closure is an anonymous block of code. In Groovy, it is an instance of the Closure class. Closures can take 0 or more parameters and always return a value. Additionally, a closure may access surrounding variables outside its scope and use them — along with its local variables — during execution.

How do you break each Groovy?

Nope, you can't abort an "each" without throwing an exception. You likely want a classic loop if you want the break to abort under a particular condition. Alternatively, you could use a "find" closure instead of an each and return true when you would have done a break.

What is -> in Groovy?

It is used to separate where you declare bindings for your closure from the actual code, eg: def myClosure = { x, y -> x + y } the part before -> declares that the closure has two arguments named x and y while the second part is the code of the closure.

How do I use lambda expression in Groovy?

The Groovy syntax doesn't support the lambda expressions, but we can rely on closure coersion to use Groovy closures as Java lambda expressions in our code. In the following sample we use the Java Streams API. Instead of lambda expressions for the filter and map methods we use Groovy closures.


1 Answers

I think you want to use find instead of each (at least for the specified example). Closures don't directly support break.

Under the covers, groovy doesn't actually use a closure either for find, it uses a for loop.

Alternatively, you could write your own enhanced version of find/each iterator that takes a conditional test closure, and another closure to call if a match is found, having it break if a match is met.

Here's an example:

 Object.metaClass.eachBreak = { ifClosure, workClosure ->     for (Iterator iter = delegate.iterator(); iter.hasNext();) {         def value = iter.next()         if (ifClosure.call(value)) {             workClosure.call(value)             break         }             } }  def a = ["foo", "bar", "baz", "qux"]  a.eachBreak( { it.startsWith("b") } ) {     println "working on $it" }  // prints "working on bar" 
like image 134
Ted Naleid Avatar answered Oct 14 '22 10:10

Ted Naleid