Операторы перехода

В Kotlin определено три оператора перехода

  • return по умолчанию производит возврат из ближайшей окружающей его функции или анонимной функции
  • break завершает выполнение цикла
  • continue продолжает выполнение цикла со следующего его шага, без обработки оставшегося кода текущей итерации

Метки операторов break и continue

Любое выражение в Kotlin может быть помечено меткой label. Метки имеют идентификатор в виде знака @. Например: метки abc@, fooBar@ являются корректными (см. грамматика). Для того, чтобы пометить выражение, мы просто ставим метку перед ним

loop@ for (i in 1..100) {
  // ...
}

Теперь мы можем уточнить значения операторов break или continue с помощью меток:

loop@ for (i in 1..100) {
  for (j in 1..100) {
    if (...)
      break@loop
  }
}

Оператор break, отмеченный @loop, переводит выполнение кода к той его части, которая находится сразу после соответствующей метки loop@. Оператор continue продолжает цикл со следующей его итерации.

Возврат к меткам

В Kotlin функции могут быть вложены друг в друга с помощью анонимных объектов, локальных функций(ориг.:local functions) и function literals. Подходящий return позволит вернуться из внешней функции. Одним из самых удачных применений этой синтаксической конструкции служит возврат из лямбда-выражения. Подумайте над этим утверждением, читая данный пример:

fun foo() {
  ints.forEach {
    if (it == 0) return
    print(it)
  }
}

Опертор return возвращается из ближаейшей функции, в нашем случае foo. (Обратите внимание, что такой местный возврат поддерживается только лямбда-выражениями, переданными инлайн-функциям.) Если нам надо вернуться из лямбда-выражения, к оператору стоит поставить метку и тем самым сделать уточнение для ключевого слова return:

fun foo() {
  ints.forEach lit@ {
    if (it == 0) return@lit
    print(it)
  }
}

Теперь он возвращает только из лямда-выражения. Зачастую намного более удобно указывать метки неявно: такие метки имеют такое же имя, как и функция, к которой относится лямбда.

fun foo() {
  ints.forEach {
    if (it == 0) return@forEach
    print(it)
  }
}

Возможно также использование анонимной функции в качестве альтернативы лямбда-выражениям. Оператор return вовзращается из самой анонимной функции.

fun foo() {
  ints.forEach(fun(value: Int) {
    if (value == 0) return
    print(value)
  })
}

При возвращении значения парсер отдаёт предпочтение специализированному возврату, типа

return@a 1

что значит "верни 1 в метке @a, а не "верни выражение с меткой (@a 1)".