Kotlin a de très jolies fonctions itératives, comme forEach
ou repeat
, mais je ne parviens pas à faire en sorte que les opérateurs break
et continue
(avec les opérateurs locaux). et non local):
repeat(5) {
break
}
(1..5).forEach {
continue@forEach
}
Le but est d’imiter les boucles habituelles avec une syntaxe fonctionnelle aussi proche que possible. C'était certainement possible dans certaines versions plus anciennes de Kotlin, mais j'ai du mal à reproduire la syntaxe.
Le problème pourrait être un bug avec les étiquettes (M12), mais je pense que le premier exemple devrait quand même fonctionner.
Il me semble que j'ai lu quelque part une astuce/une annotation spéciale, mais je n’ai trouvé aucune référence à ce sujet. Peut ressembler à ceci:
public inline fun repeat(times: Int, @loop body: (Int) -> Unit) {
for (index in 0..times - 1) {
body(index)
}
}
Modifier :
Selon Kotlin anciens documents - le lien est brisé , il devrait être possible d’utiliser des annotations. Cependant, il n'est pas encore implémenté.
Break et continue pour les structures de contrôle personnalisées ne sont pas encore implémentés
Le numéro pour cette fonctionnalité a 3 ans, donc je suppose que cela ne va pas être corrigé.
Réponse originale :
Puisque vous fournissez un (Int) -> Unit
, vous ne pouvez pas en sortir, car le compilateur ne sait pas qu’il est utilisé dans une boucle.
Vous avez peu d'options:
Utilisez une boucle for régulière:
for (index in 0..times - 1) {
// your code here
}
Si la boucle est le dernier code de la méthode
vous pouvez utiliser return
pour sortir de la méthode (ou return value
_ s'il ne s'agit pas de la méthode unit
).
Utiliser une méthode
Créez une méthode de méthode de répétition personnalisée qui renvoie Boolean
pour continuer.
public inline fun repeatUntil(times: Int, body: (Int) -> Boolean) {
for (index in 0..times - 1) {
if (!body(index)) break
}
}
Cela imprimera 1 à 5. Le return@forEach
agit comme le mot clé continue
en Java, ce qui signifie que, dans ce cas, il exécute toujours toutes les boucles, mais passe à l'itération suivante si la valeur est supérieure à 5.
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it > 5) return@forEach
println(it)
}
}
Cela imprimera 1 à 10 mais saute 5.
fun main(args: Array<String>) {
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
nums.forEach {
if (it == 5) return@forEach
println(it)
}
}
Essayez-les à Kotlin Playground .
Vous pouvez utiliser retour de l'expression lambda qui imite un continue
ou break
en fonction de votre utilisation.
Ceci est couvert dans la question connexe: Comment puis-je faire une "pause" ou "continuer" quand dans une boucle fonctionnelle dans Kotlin?
Comme le la documentation de Kotlin dit , utiliser return
est la voie à suivre. La bonne chose à propos de kotlin est que si vous avez des fonctions imbriquées, vous pouvez utiliser des étiquettes pour écrire explicitement d'où provient votre retour:
Fonction Retour de la fonction
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // non-local return directly to the caller of foo()
print(it)
}
println("this point is unreachable")
}
et Retour local (il n'arrête pas de passer par forEach = continuation)
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}
Consultez la documentation, c'est vraiment bien :)
Une pause peut être réalisée en utilisant:
//Will produce"12 done with nested loop"
//Using "run" and a tag will prevent the loop from running again. Using return@forEach if I>=3 may look simpler, but it will keep running the loop and checking if i>=3 for values >=3 which is a waste of time.
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
Et une poursuite peut être réalisée avec:
//Will produce: "1245 done with implicit label"
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with implicit label")
}
Comme tout le monde le recommande ici ... lisez la documentation: P https://kotlinlang.org/docs/reference/returns.html#return-at-labels
continue
comportement de type dans forEach
list.forEach { item -> // here forEach give you data item and you can use it
if () {
// your code
return@forEach // Same as continue
}
// your code
}
pour le comportement de type break
, vous devez utiliser for until
for (index in 0 until list.size) {
val item = listOfItems[index] // you can use data item now
if () {
// your code
break
}
// your code
}