Non-local returns
В Kotlin вы можете использовать обыкновенный, безусловный return
только для выхода из именованной или анонимной функции. Это значит, что для выхода из лямбды вам нужно использовать метку. Обычный return
запрещён внутри лямбды, потому что она не может заставить внешнюю функцию завершиться.
fun foo() {
ordinaryFunction {
return // ERROR: нельзя заставить `foo` завершиться здесь
}
}
Но если функция, в которую передана лямбда, встроена, то return
также будет встроен, поэтому так делать можно:
fun foo() {
inlined {
return // OK: лямбда встроена
}
}
Такие return (находящиеся внутри лямбд, но завершающие внешнюю функцию) называются нелокальными (ориг.: non-local). Такие конструкции обычно используются в циклах, которые являются inline-функциями:
fun hasZeros(ints: List<Int>): Boolean {
ints.forEach {
if (it == 0) return true // return из hasZeros
}
return false
}
Заметьте, что некоторые inline-функции могут вызывать переданные им лямбды не напрямую в теле функции, а из иного контекста, такого как локальный объект или вложенная функция. В таких случаях, нелокальное управление потоком выполнения также запрещено в лямбдах. Чтобы указать это, параметр лямбды необходимо отметить модификатором crossinline
.
inline fun f(crossinline body: () -> Unit) {
val f = object: Runnable {
override fun run() = body()
}
// ...
}