Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The when expression in Kotlin evaluates a target argument against multiple branch conditions. By combining when with the in or !in operators, a branch can evaluate whether the target argument exists within a ClosedRange, OpenEndRange, Progression, Collection, Array, or any custom type that implements the contains operator function.

Syntax Mechanics

To evaluate a range or collection within a when block, the branch condition must be prefixed with the in (contains) or !in (does not contain) operator, followed by the range or collection definition. The arrow -> must be followed by a valid expression, statement, or block.
fun evaluateTarget(target: Int, start: Int, end: Int, validNumbers: List<Int>) {
    when (target) {
        in start..end -> { /* Evaluates true if target >= start AND target <= end */ }
        in start..<end -> { /* Evaluates true if target >= start AND target < end */ }
        !in start..end -> { /* Evaluates true if target < start OR target > end */ }
        in validNumbers -> { /* Evaluates true if validNumbers.contains(target) */ }
        else -> { /* Mandatory fallback if used as an expression */ }
    }
}

Under the Hood

  1. Operator Delegation: The in keyword in a when branch is syntactic sugar for the contains() operator function. For example, in a..b translates to (a..b).contains(target), and in collection translates to collection.contains(target).
  2. Primitive Optimization: For primitive types (Int, Long, Char), the Kotlin compiler optimizes the in range check. Instead of allocating a range object and invoking contains(), it compiles directly to highly efficient boolean comparison logic (e.g., start <= target && target <= end).
  3. Sequential Evaluation: when branches are evaluated top-to-bottom. The expression short-circuits and executes the first branch where the in condition evaluates to true.

Supported Types for in Checks

The when check using in is not limited to numeric primitives. It supports any type that forms a valid range or provides a containment check mechanism.
  • Standard Progressions: IntRange, LongRange, and CharRange.
  • Collections and Arrays: Any Iterable, Collection (such as List or Set), or Array.
  • Custom Comparables: Any class implementing Comparable<T> can be used with the .. operator to create a ClosedRange.
  • Custom Contains: Any arbitrary type that defines an operator fun contains(value: T): Boolean.
fun checkVersion(version: String, supportedVersions: Set<String>) {
    when (version) {
        in "1.0.0".."1.9.9" -> { /* Lexicographical string comparison */ }
        in supportedVersions -> { /* Evaluates via Set.contains() */ }
    }
}

Exhaustiveness Requirements

Since Kotlin 1.7, exhaustiveness is strictly enforced for when statements if the subject is an enum, sealed class/interface, or Boolean. However, for types typically evaluated with ranges or collections (such as Int, Long, or String), the compiler cannot statically verify that a set of ranges covers the entire domain of the type (e.g., all 32 bits of an Int). Because of this limitation, an else branch is strictly required whenever a when block containing ranges is used as an expression (where it returns a value to a variable). When used as a statement with non-exhaustive types like Int or String, the else branch remains optional.
fun evaluateValue(value: Int): String {
    // Used as an expression: 'else' is mandatory
    val result = when (value) {
        in 1..10 -> "Low"
        in 11..100 -> "High"
        else -> "Out of bounds" 
    }
    return result
}
Master Kotlin with Deep Grasping Methodology!Learn More