Returns and Jumps

Kotlin has three structural jump operators

  • return{: .keyword }. By default returns from the nearest enclosing function or anonymous function.
  • break{: .keyword }. Terminates the nearest enclosing loop.
  • continue{: .keyword }. Proceeds to the next step of the nearest enclosing loop.

Break and Continue Labels

Any expression in Kotlin may be marked with a label{: .keyword }. Labels have the form of an identifier followed by the @ sign, for example: abc@, fooBar@ are valid labels (see the grammar). To label an expression, we just put a label in front of it

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

Now, we can qualify a break{: .keyword } or a continue{: .keyword } with a label:

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

A break{: .keyword } qualified with a label jumps to the execution point right after the loop marked with that label. A continue{: .keyword } proceeds to the next iteration of that loop.

Return at Labels

With function literals, local functions and object expression, functions can be nested in Kotlin. Qualified return{: .keyword }s allow us to return from an outer function. The most important use case is returning from a lambda expression. Recall that when we write this:

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

The return{: .keyword }-expression returns from the nearest enclosing function, i.e. foo. (Note that such non-local returns are supported only for lambda expressions passed to inline functions.) If we need to return from a lambda expression, we have to label it and qualify the return{: .keyword }:

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

Now, it returns only from the lambda expression. Oftentimes it is more convenient to use implicits labels: such a label has the same name as the function to which the lambda is passed.

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

Alternatively, we can replace the lambda expression with an anonymous function. A return{: .keyword } statement in an anomymous function will return from the anonymous function itself.

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

When returning a value, the parser gives preference to the qualified return, i.e.

return@a 1

means "return 1 at label @a" and not "return a labeled expression (@a 1)".

results matching ""

    No results matching ""