1. Introduction

Kotlin provides many features and tools that enhance code readability, including the when expression, which replaces traditional switch statements.

However, when using when expressions, we may encounter the warning: “Return can be lifted out of when” — indicating that a return statement within a when expression is unnecessary and can be optimized. Understanding how to address this warning helps us to write cleaner Kotlin code.

In this tutorial, we’ll explore several approaches to resolve the warning that a return can be lifted out of a when expression.

2. Moving return Statement Outside of when

Let’s consider a Kotlin code snippet where the warning appears:

fun getErrorCode(type: String): String {
    when (type) {
        "error" -> return "404"
        "success" -> return "200"
        else -> return "Unknown type"
    }
}

Each branch of the when expression contains a return statement in this example. We notice the warning message displayed in the IDE:

Warning in IDE

Specifically, Kotlin can optimize this code by lifting the return out of the when block, thus simplifying the structure.

Let’s now see a new version of this expression that lifts the return statement out of the expression to address the warning:

fun getErrorCodeOptimized(type: String): String {
    return when (type) {
        "error" -> "404"
        "success" -> "200"
        else -> "Unknown type"
    }
}

The code becomes more concise, readable, and idiomatic by removing the redundant return statements from within the when block. Consequently, this optimization improves both readability and maintainability.

3. Using Expression Body for Single-Expression Methods

Another way we can optimize our getErrorCode() method from above is by using the expression body syntax for single-expression methods:

fun getErrorCodeOptimizedUsingExpressionBodySyntax(type: String): String = when (type) {
    "error" -> "404"
    "success" -> "200"
    else -> "Unknown type"
}

This approach simplifies methods that directly return the result of an expression, making it more concise.

With an expression body for the getErrorCode() method, we can skip all return statements within our function.

4. Refactoring Complex when Statements

when expression containing multiple return statements may trigger the warning about lifting the return out of the when block. However, if it does not, restructuring the code can still simplify and improve readability.

Let’s consider a complex when expression:

fun categorizeNumber(number: Int): String {
    when {
        number < 0 -> {
            println("Logging negative number: $number")
            return "Negative"
        }
        number % 2 == 0 -> {
            println("Logging even number: $number")
            return "Even"
        }
        else -> {
            println("Logging odd number: $number")
            return "Odd"
        }
    }
}

In this example, each branch of the when expression performs additional operations before returning a value. Simplifying the when block while retaining these operations requires careful restructuring:

fun categorizeNumberOptimized(number: Int): String {
    return when {
        number < 0 -> {
            println("Logging negative number: $number")
            "Negative"
        }
        number % 2 == 0 -> {
            println("Logging even number: $number")
            "Even"
        }
        else -> {
            println("Logging odd number: $number")
            "Odd"
        }
    }
}

We can simplify the code by lifting the return statement out of the when block and also ensure other operations within the expression are retained.

5. Simplifying when With Variable Assignment

In some cases, we can also assign the result of the when expression to a variable to make the code easier to understand. This helps use the results from the when expression later in a method.

Let’s see an example:

fun processStatus(status: String): String {
     when (status) {
        "active" -> return "Processing"
        "inactive" -> return "Idle"
        "error" -> return "Error occurred"
        else -> return "Unknown status"
    }
}

We can store the result in a variable to log the value before returning:

fun processStatusOptimized(status: String): String {
    val result = when (status) {
        "active" -> "Processing"
        "inactive" -> "Idle"
        "error" -> "Error occurred"
        else -> "Unknown status"
    }
    println("Processing status: $result")
    return result
}

In this version, we assign the result of the when expression to a variable instead of returning from the when expression.

6. Conclusion

In this article, we’ve explored various approaches to resolving the warning, “Return can be lifted out of ‘when'” in Kotlin. We started by understanding the warning and its implications.

First, we moved the return statement outside the when block. Next, we utilized the expression body syntax for single-expression methods.

Additionally, we addressed when statements with complex branches and additional operations. Finally, we solved this warning by assigning the result of the expression to a variable instead, thus removing redundant return statements.

As always, the code used in this article is available over on GitHub.