Labeled Returns

Sometimes, in Kotlin, you will see a return followed by @ and some name, such as return@overthere. This is a “labeled return” and allows you to have some control over where return actually returns to.

Where return Goes By Default

Frequently, there is little debate over the behavior of return:

fun theFunction() {
  return
}

Here, return returns from theFunction().

Things get messier when we start to introduce nested constructs, such as lambda expressions:

fun somethingifier(items: List<String>) {
  items.forEach {
    if (it.length == 3) return else println(it)
  }

  println("Done!")
}

fun main() {
  somethingifier(listOf("this", "is", "a", "fun", "bit", "of", "Kotlin"))
}

Here, we return if we encounter a three-letter word. You might think that this would just exit the lambda expression, so we would print “Done!”. However, by default, return returns from whatever function it is in. Lambda expressions are not functions. So, our return returns entirely from somethingifier(), bypassing the “Done!” println() statement. So, we get:

this is a

While a lambda expression is not a function, an anonymous function is a function. Rewriting the above snippet to use an anonymous function changes the behavior a bit:

fun somethingifier(items: List<String>) {
  items.forEach(fun(it: String) {
    if (it.length == 3) return else println(it)
  })

  println("Done!")
}

fun main() {
  somethingifier(listOf("this", "is", "a", "fun", "bit", "of", "Kotlin"))
}

Now, our “business logic” is contained in an anonymous function, not a lambda expression. return, by default, returns from whatever function it is in, so our return returns from the anonymous function. That just completes the current pass in the forEach loop and allows the loop to continue. As a result, we just skip the three-letter words, and we get “Done!” at the end:

this
is
a
of
Kotlin
Done!

Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.