Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it possible to break out of closure in groovy

Tags:

groovy

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 in 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 this in Groovy?

" this " in a block mean in Groovy always (be it a normal Java-like block or a Closure) the surrounding class (instance). " owner " is a property of the Closure and points to the embedding object, which is either a class (instance), and then then same as " this ", or another Closure.

What is closure in gradle?

Note in Gradle DSL, closures are frequently (and idiomatically) used as the last method parameter to configure some object. This is a pattern called configuration closure.


I often forget that Groovy implements an "any" method.

[1, 2, 3].any
{   
   println it
   return (it == 2)
}​

12/05/2013 Heavily Edited.

Answering the question that was asked.

Is it possible to break out of a Closure?

You would "break" out of a closure by issuing the return keyword. However that isn't helpful in the example that is given. The reason for this is that the closure (think of it as a method) is called by the each method for every item in the collection.

If you run this example you will see it will print 1 then 3.

[1, 2, 3].each {
  if (it == 2) return
  println(it)
}

Why break in the context of each doesn't make sense.

To understand why you cannot break out of the each method like you could break out of a for loop you need to understand a bit of what is actually happening. Here is a gross simplification what the each method on a collection does.

myEach([0,1,3])

void myEach(List things) {
    for (i in things) {
        myEachMethod(i)
    }
}

void myEachMethod(Object it) { // this is your Closure
    if(it == 2) return
    println it
}

As you can see the closure is basically a method that can be passed around. Just as in java you cannot break from within method call or closure.

What to do instead of breaking from each.

In Groovy you are supposed to express your code using high level abstractions as such primitive looping is not idiomatic. For the example that you gave I would consider making use of findAll. For example:

[1,2,3].findAll { it < 2 }.each { println it }

I hope this helps you understand what is going on.

Answering the implied question.

Can you break out of the Collection.each iterations against your supplied closure?

You cannot break out of the each method without throwing and catching an exception as John Wagenleitner has said. Although I would argue that throwing and catching an exception in the name of flow control is a code smell and a fellow programmer might slap your hands.


You can throw an exception:

try {
    [1, 2, 3].each { 
        println(it)
        if (it == 2)
            throw new Exception("return from closure") 
    }
} catch (Exception e) { }

Use could also use "findAll" or "grep" to filter out your list and then use "each".

[1, 2, 3].findAll{ it < 3 }.each{ println it }

Take a look at Best pattern for simulating continue in groovy closure for an extensive discussion.


Try to use any instead of each

def list = [1, 2, 3, 4, 5, -1, -2]
list.any { element ->
    if (element > 3)
    return true // break
    println element
}

The result : 1, 2, 3


Just using special Closure

// declare and implement:
def eachWithBreak = { list, Closure c ->
  boolean bBreak = false
  list.each() { it ->
     if (bBreak) return
     bBreak = c(it)
  }
}

def list = [1,2,3,4,5,6]
eachWithBreak list, { it ->
  if (it > 3) return true // break 'eachWithBreak'
  println it
  return false // next it
}