while when pass loop loops functional-programming break kotlin continue

loops - when - return function kotlin



¿Cómo hago un "descanso" o "continuar" cuando estoy en un ciclo funcional dentro de Kotlin? (4)

En Kotlin, no puedo hacer un break o continue dentro de un bucle de función y mi lambda, como puedo hacerlo desde un ciclo for normal. Por ejemplo, esto no funciona:

(1..5).forEach { continue@forEach // not allowed, nor break@forEach }

Hay documentación antigua que menciona que esto está disponible, pero parece que nunca se implementó. ¿Cuál es la mejor manera de obtener el mismo comportamiento cuando quiero continue o break desde el lambda?

Nota: esta pregunta fue escrita y respondida intencionalmente por el autor ( Preguntas de respuesta automática ), de modo que las respuestas idiomáticas a los temas de Kotlin comúnmente formulados están presentes en SO. También para aclarar algunas respuestas realmente antiguas escritas para alfas de Kotlin que no son precisas para Kotlin actual.


Puede usar return de la expresión lambda que imita un continue o break dependiendo de su uso.

Aquí hay un ejemplo que imita continue :

(1..5).forEach { if (it == 3) return@forEach // mimic continue@forEach // ... do something more }

Y puede ir más complicado y usar etiquetas cuando tiene situaciones de anidamiento o confusas:

(1..3).forEach outer@ { x -> (1..3).forEach inner@ { y -> if (x == 2 && y == 2) return@outer // mimic continue@outer if (x == 1 && y == 1) return@inner // mimic continue@inner // ... do something more } }

Si quiere hacer un break , necesita algo fuera del ciclo del que pueda regresar, aquí utilizaremos la función run() para ayudarnos:

run breaker@ { (1..20).forEach { x -> if (x == 5) return@breaker // mimic break@forEach // ... do something more } }

En lugar de run() , podría ser let() o apply() o cualquier cosa que tenga naturalmente rodeando el para forEach lugar que quiera romper. Pero también se saltará el código dentro del mismo bloque que sigue a forEach así que tenga cuidado.

Estas son funciones en línea así que realmente no agregan sobrecarga.

Lea los documentos de referencia de Kotlin para Devoluciones y Saltos para todos los casos especiales, incluso para funciones anónimas.

Aquí hay una prueba unitaria que prueba que todo esto funciona:

@Test fun testSo32540947() { val results = arrayListOf<Pair<Int,Int>>() (1..3).forEach outer@ { x -> (1..3).forEach inner@ { y -> if (x == 2 && y == 2) return@outer // continue @outer if (x == 1 && y == 1) return@inner // continue @inner results.add(Pair(x,y)) } } assertEquals(listOf(Pair(1,2), Pair(1,3), Pair(2,1), Pair(3,1), Pair(3,2), Pair(3,3)), results) val results2 = arrayListOf<Int>() run breaker@ { (1..20).forEach { x -> if (x == 5) return@breaker results2.add(x) } } assertEquals(listOf(1,2,3,4), results2) }


Si hay una necesidad de usar continue o break , no es ideal para usar para cada forEach comparar con el for-loop normal

Si realmente desea encadenar su comando, y actuar como un bucle for, use la cadena funcional normal, en lugar de forLoop

Ej. Para

for(i in 0 until 100 step 3) { if (i == 6) continue if (i == 60) break println(i) }

Utilice el map como for-loop, filterNot como continue y asSequence() & first para break

(0 until 100 step 3).asSequence() .filterNot { it == 6 } .map { println(it); it } .first { it == 60 }


takeWhile función takeWhile stdlib se puede usar en lugar de break.

Por ejemplo,

val array = arrayOf(2, 8, 4, 5, 13, 12, 16) array.takeWhile { it % 2 == 0 }.forEach { println(it) } // break on odd array.takeWhile { it % 3 != 0 }.forEach { println(it) } // break on 3 * n


forEach con break puede ser sustituido específicamente con any function :

(1..20).any { x -> (x == 5).apply { // break on true if (!this) { results2.add(x) } } }

O posiblemente incluso más corto:

(1..20).any { x -> results2.add(x) x == 4 // break on true }