Это возможно break
из Groovy .each{Closure}
, или я должен вместо этого использовать классический цикл?
Это возможно break
из Groovy .each{Closure}
, или я должен вместо этого использовать классический цикл?
Ответы:
Нет, вы не можете прервать «каждый» без исключения. Скорее всего, вам нужен классический цикл, если вы хотите, чтобы разрыв прерывался при определенных условиях.
В качестве альтернативы вы можете использовать замыкание «найти» вместо «каждый» и возвращать значение «истина», когда вы сделали перерыв.
Этот пример будет прерван до обработки всего списка:
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.
Также очень легко написать свои собственные методы итератора с пользовательским поведением разрыва, которые принимают замыкания:
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
find
лучше , чем any
- см другой ответ ниже от @Michal , что один работает для меня
def test = [2] test.findResult{ it * 2 }
вернет 4 вместо 2
Замените каждую петлю любым замыканием.
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
any()
таким образом немного вводит в заблуждение, но оно, безусловно, работает и дает вам возможность сломаться или продолжить .
Нет, вы не можете выйти из замыкания в 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: поиск, grep, collect, inject и т. Д. Они обычно принимают некоторую «конфигурацию», а затем «знают», как выполнить итерацию за вас, чтобы вы могли избежать императивных циклов, где это возможно.
Просто используя специальное закрытие
// 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
}
(1..10) .each {
если (это <5)
распечатайте это
еще
вернуть ложь
each
, оно просто не печатает значения больше 4. Это else
излишне, ваш код сделал бы то же самое без него. Кроме того, вы можете доказать, each
что не порвется, return false
если вы поставите println "not breaking"
сразу после else
и только до этого return false
.
Вы могли бы прорваться RETURN
. Например
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
Меня устраивает!
any
метод массива, вернув false
. Вы не можете нарушить each
метод таким же образом.