Возможно ли break
от Groovy .each{Closure}
, или я должен использовать классический цикл?
Можете ли вы выйти из Groovy "каждого" закрытия?
Ответ 1
Нет, вы не можете прервать "каждый", не выбрасывая исключение. Вероятно, вам нужен классический цикл, если вы хотите, чтобы прерывание прерывалось в определенном состоянии.
В качестве альтернативы вы можете использовать закрытие "найти" вместо каждого и вернуть true, если бы вы сделали перерыв.
Этот пример прервется перед обработкой всего списка:
def a = [1, 2, 3, 4, 5, 6, 7]
a.find {
if (it > 5) return true // break
println it // do the stuff that you wanted to before break
return false // keep looping
}
Печать
1
2
3
4
5
но не печатает 6 или 7.
Также очень легко написать собственные методы итератора с пользовательским поведением break, которые принимают закрытие:
List.metaClass.eachUntilGreaterThanFive = { closure ->
for ( value in delegate ) {
if ( value > 5 ) break
closure(value)
}
}
def a = [1, 2, 3, 4, 5, 6, 7]
a.eachUntilGreaterThanFive {
println it
}
Также печатает:
1
2
3
4
5
Ответ 2
Замените цикл each на любую.
def list = [1, 2, 3, 4, 5]
list.any { element ->
if (element == 2)
return // continue
println element
if (element == 3)
return true // break
}
Выход
1
3
Ответ 3
Нет, вы не можете выйти из закрытия в Groovy, не вызывая исключения. Кроме того, вы не должны использовать исключения для потока управления.
Если вы обнаружите, что хотите выйти из закрытия, вы должны сначала подумать, почему вы хотите это сделать, а не как это сделать. Первое, что нужно рассмотреть, - это замена рассматриваемого замыкания одной из Groovy (концептуальных) функций более высокого порядка. Следующий пример:
for ( i in 1..10) { if (i < 5) println i; else return}
становится
(1..10).each{if (it < 5) println it}
становится
(1..10).findAll{it < 5}.each{println it}
что также помогает ясности. В нем говорится о намерении вашего кода намного лучше.
Потенциальный недостаток в приведенных примерах заключается в том, что итерация останавливается только в начале первого примера. Если у вас есть соображения производительности, вы можете остановить его прямо там и там.
Однако для большинства случаев использования, связанных с итерациями, вы обычно можете использовать один из методов Groovy find, grep, collect, inject и т.д. Обычно они берут некоторую "конфигурацию", а затем "знают", как делать итерацию для вас, чтобы вы могли избежать по возможности обязательного цикла.
Ответ 4
Просто используя специальное закрытие
// 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
}
Ответ 5
(1..10).each {
если (it < 5)
println it
еще
return false
Ответ 6
Вы можете сломать RETURN
. Например
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
Это работает для меня!