Skip to main content

Kotlin Return Jump

Introduction

In Kotlin, the return statement is a control flow mechanism that allows you to exit from a function, returning a value if the function is non-void (returns something other than Unit). The return jump is an essential part of Kotlin's control flow system, giving you control over when a function should terminate execution and what value it should provide back to the caller.

Unlike some other programming languages, Kotlin's return statement has additional functionality when used with labels, enabling you to control which function or lambda expression to return from when dealing with nested code structures.

Basic Return Statement

In its simplest form, the return statement exits the nearest enclosing function and returns the specified value to the caller.

Syntax

kotlin
return [expression]

Where expression is optional and represents the value to be returned (required for non-Unit functions).

Examples

Simple Function Return

kotlin
fun multiply(a: Int, b: Int): Int {
return a * b
}

fun main() {
val result = multiply(5, 3)
println("5 × 3 = $result")
}

Output:

5 × 3 = 15

Early Return for Conditional Logic

The return statement is often used for early exits from functions based on conditions:

kotlin
fun divide(a: Int, b: Int): Int? {
if (b == 0) {
println("Cannot divide by zero")
return null
}
return a / b
}

fun main() {
println("10 ÷ 2 = ${divide(10, 2)}")
println("10 ÷ 0 = ${divide(10, 0)}")
}

Output:

10 ÷ 2 = 5
Cannot divide by zero
10 ÷ 0 = null

Return from Lambda Expressions

By default, when you use return inside a lambda expression, it will return from the function that contains the lambda, not just from the lambda itself.

kotlin
fun processNumbers() {
val numbers = listOf(1, 2, 3, 4, 5)

numbers.forEach {
if (it == 3) return // Returns from the processNumbers function
println(it)
}

println("This line is never executed if the list contains 3")
}

fun main() {
processNumbers()
println("Function completed")
}

Output:

1
2
Function completed

Notice that when it == 3, the entire processNumbers function is terminated, not just the lambda in forEach.

Labeled Returns

Kotlin allows you to label your expressions and then use these labels with the return statement to specify which function or lambda to return from.

Syntax

kotlin
label@ expression

// To return from labeled expression
return@label [value]

Examples

Return from a Specific Lambda

kotlin
fun processNumbersWithLabel() {
val numbers = listOf(1, 2, 3, 4, 5)

numbers.forEach label@ {
if (it == 3) return@label // Returns from the lambda, not from the function
println(it)
}

println("This line WILL be executed even if the list contains 3")
}

fun main() {
processNumbersWithLabel()
println("Function completed")
}

Output:

1
2
4
5
This line WILL be executed even if the list contains 3
Function completed

Implicit Labels

Kotlin allows you to use the name of the higher-order function as a label, without explicitly defining it:

kotlin
fun processNumbersWithImplicitLabel() {
val numbers = listOf(1, 2, 3, 4, 5)

numbers.forEach {
if (it == 3) return@forEach // Implicit label using the function name
println(it)
}

println("This line will execute")
}

fun main() {
processNumbersWithImplicitLabel()
}

Output:

1
2
4
5
This line will execute

Anonymous Functions with Returns

Another way to handle returns in nested structures is to use anonymous functions instead of lambda expressions:

kotlin
fun processNumbersAnonymous() {
val numbers = listOf(1, 2, 3, 4, 5)

numbers.forEach(fun(value) {
if (value == 3) return // Returns from the anonymous function
println(value)
})

println("This line will execute")
}

fun main() {
processNumbersAnonymous()
}

Output:

1
2
4
5
This line will execute

Real-World Application Examples

Input Validation

kotlin
fun validateUserInput(username: String, password: String): Boolean {
// Check username conditions
if (username.isEmpty()) {
println("Username cannot be empty")
return false
}

if (username.length < 3) {
println("Username too short")
return false
}

// Check password conditions
if (password.length < 8) {
println("Password must be at least 8 characters")
return false
}

if (!password.any { it.isDigit() }) {
println("Password must contain at least one digit")
return false
}

// If all validations pass
println("Input validation successful")
return true
}

fun main() {
validateUserInput("john", "password123") // Valid
validateUserInput("a", "password123") // Invalid username
validateUserInput("john", "password") // Invalid password (no digit)
}

Output:

Input validation successful
Username too short
Password must contain at least one digit

Processing Collection Items Safely

kotlin
fun processUserData(users: List<User?>) {
users.forEach { user ->
// Skip null users
if (user == null) return@forEach

// Skip users with missing information
if (user.name.isEmpty() || user.email.isEmpty()) {
println("Skipping user with incomplete data")
return@forEach
}

// Process valid user
println("Processing user: ${user.name}, Email: ${user.email}")
}
}

data class User(val name: String, val email: String)

fun main() {
val users = listOf(
User("Alice", "[email protected]"),
null,
User("Bob", ""),
User("Charlie", "[email protected]")
)

processUserData(users)
}

Output:

Processing user: Alice, Email: [email protected]
Skipping user with incomplete data
Processing user: Charlie, Email: [email protected]

Summary

The return jump in Kotlin is a powerful control flow mechanism that allows you to:

  1. Exit functions with or without returning values
  2. Implement early returns for cleaner conditional code
  3. Control the scope of returns in nested structures using labels
  4. Create more readable and maintainable code with explicit control flow

Understanding how return works in different contexts is essential for writing effective Kotlin code, particularly when working with higher-order functions and lambdas.

Additional Resources

Practice Exercises

  1. Write a function that processes a list of numbers and returns the first number divisible by 7, or null if none exists.

  2. Create a function that checks user credentials with nested validation steps, using appropriate return statements.

  3. Write a function that processes a list of strings and prints each one, but skips any that are empty or contain only whitespace. Use labeled returns.

  4. Create a function that searches through a nested data structure (e.g., a list of lists) and returns early once a specific value is found.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)