Breaking out of closures
gotcha, groovy June 28th. 2008, 1:58pmcoming from java I’m used to using break & continue to manipulate loops. Groovy doesn’t allow these keywords, so iterating with closures presented a problem.
Consider a piece of code like:
Listpeople = // instantiate some Person ’s (idiots at the back) // print the useful people for (Person person : people) { if (person.isNuisance()) { break; } System.out.println(”name : ” + person.getName()); }
To achieve the same effect in groovy, the common trick is to use .find {} rather than .each{}
find loops over all the items in the list just like each, except it breaks out and returns the current object when a true condition is returned from the closure. So there is no reason why you can’t add logic to find, and use it in this manner
class Person { String name; boolean nuisance}
def people = [new Person(name:"person1",nuisance:false),
new Person(name:"person2",nuisance:false),
new Person(name:"person3",nuisance:true),
new Person(name:"person4",nuisance:true)]
people.find() {
if (it.nuisance) return true // break out
println it.name
}
June 29th, 2008 at 5:54 am
I like this syntax to use ‘find’:
def item = people.find { it.nuisance}
println item.name
It’s more clear for me. Don’t you think?
June 29th, 2008 at 9:06 am
sure, that’s the way it’s meant to be used. But for the current example it would only find the first person.
So it’s not solving the problem
June 30th, 2008 at 10:57 am
IMO, the ‘groovier’ way would be to just write it like this:
people.findAll {
!(it.nuisance)
}.each { println it.name }
June 30th, 2008 at 8:47 pm
For quick things like this, you can use the Elvis operator to execute a statement while the condition hasn’t been met
people.find { it.nuisance ?: println(it.name) }
July 12th, 2008 at 2:42 pm
Too bad i didnt come across this blog before. Great stuff you got here. Thanks.
July 19th, 2008 at 5:03 pm
I came across this blog the other day and you got some great info here - thanks.