Я думаю, что вы хотите использовать find вместо каждого (по крайней мере, для указанного примера). Замыкания напрямую не поддерживают разрыв.
Под крышками groovy на самом деле не использует замыкание для поиска, она использует цикл for.
В качестве альтернативы, вы можете написать свою собственную улучшенную версию find / каждого итератора. для этого требуется условное тестовое закрытие и другое закрытие для вызова, если найдено совпадение, и оно прерывается при совпадении.
Вот пример:
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"
Я думаю, вы работаете на неправильном уровне абстракции. Блок .each
делает именно то, что говорит: он выполняет замыкание один раз для каждого элемента. Вместо этого вы, вероятно, захотите использовать List.indexOf
, чтобы найти правильный specificElement
, а затем выполнить ту работу, которая вам необходима для этого.
If you want to process all elements until a specific one was found you could also do something like this:
largeListOfElements.find { element ->
// do some work
element == specificElement
}
Although you can use this with any kind of "break condition". I just used this to process the first n elements of a collection by returning
counter++ >= n
at the end of the closure.
Насколько я понимаю, Groovy, способ сократить такие циклы - это выбросить определяемое пользователем исключение. Я не знаю, каким будет синтаксис (не грубый программист), но groovy работает на JVM, поэтому это будет что-то вроде:
class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}}
try { x.each{ if(it.isOk()) throw new ThisOne(it); false} }
catch(ThisOne x) { print x.foo + " is ok"; }