liveBook · Manning

Non-local return

As explained in Kotlin in Action, 2E

A non-local return exits the enclosing named function from within an invoked lambda rather than merely returning from the lambda.

A non-local return exits the enclosing named function from inside an invoked lambda. It behaves like return inside a loop or block, rather than merely ending the lambda. section 10.3.1

Returning from forEach

fun lookForAlice(people: List<Person>) { people.forEach { if (it.name == "Alice") { println("Found!") return } } println("Alice is not found") } Here, return exits lookForAlice, just as return inside a regular for loop does. forEach is inline, allowing the lambda body and its return to be compiled into the caller. section 10.3.1

Use these rules to choose the appropriate return form:

  • Use an unqualified return to leave the enclosing function, but only from a lambda passed to an inline function. section 10.3.1
  • Use a labeled return such as return@forEach or return@label to leave only the lambda and continue the enclosing function. section 10.3.2
  • Avoid unqualified returns in lambdas passed to non-inline functions, because those functions may store and invoke the lambda after the surrounding function returns. section 10.3.1
  • Use an anonymous function when a block needs multiple exit points without verbose lambda labels. section 10.3.2 section 10.4

Returning only from the lambda

fun lookForAlice(people: List<Person>) { people.forEach { if (it.name != "Alice") return@forEach print("Found Alice!") } } return@forEach skips the current lambda invocation while allowing forEach and lookForAlice to continue. section 10.3.2

Resource-management example

fun readFirstLineFromFile(fileName: String): String { BufferedReader(FileReader(fileName)).use { br -> return br.readLine() } } The return exits readFirstLineFromFile while use still provides resource-management behavior. Kotlin uses this higher-order-function pattern instead of Java's special try-with-resources syntax. section 10.2.5

How Kotlin in Action, 2E covers it

How deep it goes
Explains semantics, inline-function constraints, deferred invocation risks, labels, and anonymous-function alternatives through Kotlin examples.
Examples
Demonstrates non-local returns with forEach, use, useLines, regular loops, and labeled lambda returns.
What it assumes
Assumes familiarity with lambdas and introduces the control-flow distinction between regular loops, inline lambdas, and labeled returns.
What you can do after
Apply non-local and labeled returns safely in inline Kotlin lambdas, including iteration and resource-management code.
How it connects
Connects non-local returns with lambdas, higher-order functions, inline functions, labeled returns, anonymous functions, and resource management.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Kotlin in Action, 2E. The section links point to the parts of the book it draws on.