Pouvez-vous rompre avec une fermeture Groovy "chaque"?
Est-il possible de break
à partir D'un .each{Closure}
Groovy, ou devrais-je utiliser une boucle classique à la place?
6 réponses
Non, vous ne pouvez pas annuler un "each" sans lancer d'exception. Vous voulez probablement une boucle classique si vous voulez que la pause abandonne dans une condition particulière.
Alternativement, vous pouvez utiliser une fermeture" find " au lieu d'un each et retourner true quand vous auriez fait une pause.
Cet exemple va abandonner avant de traiter toute la liste:
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
}
Imprime
1
2
3
4
5
Mais n'imprime pas 6 ou 7.
Il est également très facile d'écrire vos propres méthodes d'itérateur avec un comportement de rupture personnalisé qui accepte les fermetures:
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
}
Imprime Également:
1
2
3
4
5
Remplacer chaque boucle avec tout fermeture.
def list = [1, 2, 3, 4, 5]
list.any { element ->
if (element == 2)
return // continue
println element
if (element == 3)
return true // break
}
Sortie
1
3
Non, vous ne pouvez pas rompre avec une fermeture dans Groovy sans lancer d'exception. En outre, vous ne devriez pas utiliser d'exceptions pour le flux de contrôle.
Si vous vous trouvez vouloir sortir de la fermeture, vous devriez d'abord penser à pourquoi vous voulez faire cela, et non pas comment le faire. La première chose à considérer pourrait être la substitution de la fermeture en question par l'une des fonctions D'ordre supérieur (conceptuelles) de Groovy. La suite exemple:
for ( i in 1..10) { if (i < 5) println i; else return}
Devient
(1..10).each{if (it < 5) println it}
Devient
(1..10).findAll{it < 5}.each{println it}
Ce qui contribue également à la clarté. Il indique l'intention de votre code beaucoup mieux.
L'inconvénient potentiel dans les exemples montrés est que l'itération ne s'arrête que tôt dans le premier exemple. Si vous avez des considérations de performance, vous voudrez peut-être l'arrêter immédiatement.
Cependant, pour la plupart des cas d'utilisation impliquant des itérations, vous pouvez généralement recourir à L'un des find, grep, collect, inject, etc. de Groovy. méthode. Ils prennent généralement une certaine " configuration "et" savent " comment faire l'itération pour vous, de sorte que vous pouvez réellement éviter la boucle impérative autant que possible.
Juste en utilisant la fermeture spéciale
// 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).chaque{
Si (il
Println il
Else
Renvoie false
Vous pourriez casser par RETURN
. Par exemple
def a = [1, 2, 3, 4, 5, 6, 7]
def ret = 0
a.each {def n ->
if (n > 5) {
ret = n
return ret
}
}
Ça marche pour moi!