Kotlin tiene estas tres expresiones:
return
. Por defecto devuelve una función o una función anónima.break
. Finaliza el bucle.continue
. Continua al siguiente paso en el bucle.
Todas esas expresiones pueden utilizarse como parte de expresiones más largas:
val s = persona.nombre ?: return
El tipo de esas expresiones es el Nothing type (tipo nada).
Etiquetas Break y Continue
Cualquier expresión en Kotlin puede ser marcada con una label
. Las etiquetas tienen la forma de un identificador seguido del signo @
. Por ejemplo: abc@
, miExpresion@
son etiquetas válidas. Para etiquetar una expresión, coloca una etiqueta delate de ella:
loop@ for (i in 1..100) { // ... }
Así, podemos utilizar break
o continue
con una etiqueta:
loop@ for (i in 1..100) { for (j in 1..100) { if (...) break@loop } }
Un break
con una etiqueta, salta a un punto de ejecución tras el bucle marcado con una etiqueta. Un continue
procede a la siguiente iteración de ese bucle.
Return en las Etiquetas
Puedes anidar funciones y expresiones de objetos. return
nos permite devolver desde una función exterior. El caso más importante es el retorno de una expresión lambda.
fun printTercerValor() { listOf(1, 2, 3, 4, 5).forEach { if (it == 3) // return no local de printTercerValor() print(it) // Este punto es alcanzable } println("Este punto es inalcanzable") }
Si necesitamos un return
de una expresión lambda, tenemos que etiquetarla:
fun printTercerValor() { listOf(1, 2, 3, 4, 5).forEach lit@{ if (it == 3) return@lit // return local al que invoca el lambda print(it) } print(" completado con una etiqueta explícita") }
Algunas veces es mejor utilizar etiquetas implícitas, es decir, etiquetas que tienen el mismo nombre que la función a la que se le pasa la lambda.
fun printTercerValor() { listOf(1, 2, 3, 4, 5).forEach { if (it == 3) return@forEach // return local al que invoca la función anónima print(it) } print(" completado con una etiqueta implícita") }
Alternativamente, podemos reemplazar la expresión lambda con una función anónima. Una declaración return
en una función anónima retornará desde la propia función anónima.
fun printTercerValor() { listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { if (value == 3) return // return local al que invoca la función anónima print(value) }) print(" completado con una función anónima") }
Ten en cuenta que el uso de returns locales en los tres ejemplos anteriores es similar al uso de continue
en los bucles. No hay un equivalente directo para break
, pero puede ser simulado añadiendo otra lambda anidada y un return no local:
fun printTercerValor() { run loop@{ listOf(1, 2, 3, 4, 5).forEach { if (it == 3) return@loop // return no local desde el lambda print(it) } } print(" completado desde un bucle anidado") }
Cuando devuelvas un valor, se da preferencia a la etiqueta return
utilizada:
return@a 1
La expresión anterior significa “devuelve 1
en la etiqueta @a
“, por lo que no sería “devuelve la expresión etiquetada como (@a 1)
“.