Bird
Raised Fist0
Kotlinprogramming~15 mins

When as expression returning value in Kotlin - Deep Dive

Choose your learning style10 modes available
Overview - When as expression returning value
What is it?
In Kotlin, the 'when' construct is a powerful tool that can be used as an expression to return a value. Unlike traditional switch statements in other languages, 'when' can evaluate multiple conditions and directly produce a result that can be assigned to a variable or used in expressions. This makes code more concise and readable by combining condition checking and value assignment in one step.
Why it matters
Using 'when' as an expression simplifies decision-making in code by reducing boilerplate and improving clarity. Without it, developers would need separate if-else chains or switch statements that don't return values, leading to more verbose and error-prone code. This feature helps write cleaner, safer, and more maintainable programs.
Where it fits
Before learning 'when' as an expression, you should understand basic Kotlin syntax, variables, and control flow like if-else statements. After mastering this, you can explore more advanced Kotlin features like sealed classes, smart casts, and functional programming concepts that often use 'when' expressions.
Mental Model
Core Idea
'When' in Kotlin is like a smart decision-maker that evaluates conditions and hands you back the answer directly.
Think of it like...
Imagine you ask a friend to pick a snack based on your mood. Instead of telling them all the rules and then waiting for their choice, you just say your mood, and they immediately hand you the perfect snack. The 'when' expression works the same way: you give it a condition, and it instantly returns the matching result.
┌───────────────┐
│   when(value) │
├───────────────┤
│ condition 1 ->│ result 1
│ condition 2 ->│ result 2
│ else       -> │ default result
└───────────────┘

Usage:
result = when(value) {
  condition1 -> result1
  condition2 -> result2
  else -> defaultResult
}
Build-Up - 7 Steps
1
FoundationBasic when syntax and usage
🤔
Concept: Introduces the basic structure of 'when' as a control flow statement.
The 'when' keyword checks a value against multiple conditions. Each condition is followed by '->' and the code to run if it matches. For example: val x = 2 when (x) { 1 -> println("One") 2 -> println("Two") else -> println("Other") } This prints 'Two' because x equals 2.
Result
Output: Two
Understanding the basic syntax is essential before using 'when' as an expression that returns values.
2
FoundationUsing when as a statement vs expression
🤔
Concept: Shows the difference between 'when' used just for actions and 'when' returning a value.
By default, 'when' can be used as a statement to run code blocks. But it can also return a value, which you can assign to a variable: val x = 3 val result = when (x) { 1 -> "One" 2 -> "Two" else -> "Unknown" } println(result) This prints 'Unknown'.
Result
Output: Unknown
Recognizing that 'when' can produce a value lets you write cleaner code by combining condition checks and assignments.
3
IntermediateMultiple conditions in when branches
🤔Before reading on: Do you think 'when' can check multiple values in one branch or only one? Commit to your answer.
Concept: Explains how to check multiple conditions in a single 'when' branch using commas.
You can test several values in one branch by separating them with commas: val x = 5 val result = when (x) { 1, 3, 5 -> "Odd small number" 2, 4, 6 -> "Even small number" else -> "Other number" } println(result) This prints 'Odd small number' because x is 5.
Result
Output: Odd small number
Knowing that multiple conditions can share one result reduces repetition and makes code more concise.
4
IntermediateUsing when without argument for complex conditions
🤔Before reading on: Can 'when' be used without a value to check arbitrary conditions? Commit to yes or no.
Concept: Shows that 'when' can be used without an argument to evaluate boolean expressions directly.
Instead of checking a single value, you can write: val x = 10 val result = when { x < 5 -> "Less than five" x in 5..10 -> "Between five and ten" else -> "More than ten" } println(result) This prints 'Between five and ten'.
Result
Output: Between five and ten
Using 'when' without an argument allows flexible condition checks, similar to if-else chains but more readable.
5
AdvancedSmart casts and type checking in when
🤔Before reading on: Do you think 'when' can automatically cast types after checking? Commit to yes or no.
Concept: Demonstrates how 'when' can check types and smart cast variables inside branches.
Kotlin can check the type of a variable and let you use it as that type inside the branch: fun describe(obj: Any): String = when (obj) { is String -> "String of length ${obj.length}" is Int -> "Integer value $obj" else -> "Unknown type" } println(describe("Hello")) println(describe(42)) Outputs: String of length 5 Integer value 42
Result
Output: String of length 5 Integer value 42
Understanding smart casts in 'when' helps write safer code without explicit casting.
6
AdvancedExhaustive when expressions and compiler checks
🤔Before reading on: Does Kotlin require 'when' expressions to cover all cases? Commit to yes or no.
Concept: Explains that when used as an expression, 'when' must be exhaustive, meaning all possible cases are handled.
If you use 'when' as an expression (returning a value), Kotlin forces you to cover all cases or provide an 'else' branch: fun getColorName(color: Color) = when (color) { Color.RED -> "Red" Color.GREEN -> "Green" Color.BLUE -> "Blue" // No else needed because all enum cases covered } If a case is missing, the compiler shows an error. This helps prevent bugs from unhandled cases.
Result
Compiler error if cases are missing; safe code if exhaustive.
Knowing about exhaustiveness ensures your code handles all possibilities, reducing runtime errors.
7
ExpertWhen expression performance and bytecode behavior
🤔Before reading on: Do you think Kotlin's 'when' compiles to a simple jump table like Java's switch? Commit to yes or no.
Concept: Explores how Kotlin compiles 'when' expressions under the hood and their performance implications.
Kotlin compiles 'when' differently depending on the cases: - For enums and constants, it often generates efficient jump tables like Java's switch. - For complex conditions or type checks, it compiles to if-else chains. Understanding this helps optimize performance-critical code by choosing appropriate 'when' usage. Example: Using enums in 'when' is faster than arbitrary conditions.
Result
Efficient bytecode for enums; less efficient for complex conditions.
Knowing compilation details helps write performant Kotlin code and avoid surprises in critical paths.
Under the Hood
The Kotlin compiler transforms 'when' expressions into bytecode that either uses jump tables for simple constant matches or chains of conditional checks for complex cases. When used as an expression, the compiler ensures all branches return a value, enforcing exhaustiveness. Smart casts inside 'when' branches rely on Kotlin's flow analysis to safely treat variables as specific types after checks.
Why designed this way?
Kotlin's 'when' was designed to be more powerful and flexible than traditional switch statements, combining pattern matching, type checking, and expression capabilities. This design reduces boilerplate and increases safety. The exhaustiveness requirement prevents bugs from missing cases, a common problem in other languages. The compiler optimizes simple cases for performance while supporting complex logic.
┌───────────────┐
│   when(value) │
├───────────────┤
│  Match enum?  ├─Yes─> Jump table bytecode
│               │
│  Complex cond?├─Yes─> if-else chain bytecode
│               │
│  Type check?  ├─Yes─> Smart cast enabled
│               │
│  Exhaustive?  ├─Compiler enforces all cases
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does 'when' always require an 'else' branch? Commit to yes or no.
Common Belief:Many think 'when' always needs an 'else' branch to compile.
Tap to reveal reality
Reality:If 'when' covers all possible cases (like all enum values), Kotlin does not require 'else'.
Why it matters:Adding unnecessary 'else' branches can hide missing cases and reduce code safety.
Quick: Is 'when' just a fancy if-else chain? Commit to yes or no.
Common Belief:Some believe 'when' is just syntactic sugar for if-else statements.
Tap to reveal reality
Reality:'When' is more powerful: it supports multiple conditions per branch, type checks, and is an expression returning values.
Why it matters:Underestimating 'when' limits its use and misses opportunities for clearer, safer code.
Quick: Does Kotlin's 'when' always compile to a jump table? Commit to yes or no.
Common Belief:People often assume 'when' compiles like Java's switch with jump tables for all cases.
Tap to reveal reality
Reality:Only simple constant or enum matches compile to jump tables; complex conditions compile to if-else chains.
Why it matters:Misunderstanding this can lead to performance surprises in critical code.
Quick: Can 'when' smart cast variables automatically? Commit to yes or no.
Common Belief:Some think 'when' does not smart cast variables after type checks.
Tap to reveal reality
Reality:'When' supports smart casts, letting you use variables as their checked types inside branches without explicit casts.
Why it matters:Not knowing this leads to unnecessary casting and verbose code.
Expert Zone
1
When used as an expression, 'when' must be exhaustive, but this exhaustiveness is checked by the compiler only for sealed classes and enums, not for all types.
2
Smart casts inside 'when' branches depend on Kotlin's flow analysis and can fail if variables are mutable or changed elsewhere, requiring careful code structure.
3
The order of branches in 'when' matters for performance and correctness, especially when using complex conditions or overlapping cases.
When NOT to use
Avoid using 'when' for very simple true/false checks where if-else is clearer. For complex pattern matching beyond 'when's capabilities, consider sealed classes with polymorphism or functional constructs like 'fold'.
Production Patterns
In production, 'when' expressions are commonly used for handling UI states, parsing input commands, and mapping enums to values. Developers often combine 'when' with sealed classes to ensure exhaustive handling of all cases, improving code safety and maintainability.
Connections
Pattern Matching in Functional Programming
'When' builds on the idea of pattern matching found in functional languages like Haskell or Scala.
Understanding 'when' as pattern matching helps grasp its power to concisely handle multiple cases and types, a concept used widely in functional programming.
Switch Statements in Java
'When' is Kotlin's more powerful and flexible alternative to Java's switch statement.
Knowing Java's switch helps appreciate how Kotlin improves on it by supporting expressions, multiple conditions, and type checks.
Decision Making in Human Psychology
'When' mirrors how humans make decisions by evaluating conditions and choosing outcomes.
Recognizing this connection shows how programming constructs model real-world thinking processes, aiding intuitive understanding.
Common Pitfalls
#1Forgetting to cover all cases in a 'when' expression, causing compiler errors.
Wrong approach:val result = when (color) { Color.RED -> "Red" Color.GREEN -> "Green" // Missing Color.BLUE and no else }
Correct approach:val result = when (color) { Color.RED -> "Red" Color.GREEN -> "Green" Color.BLUE -> "Blue" }
Root cause:Not understanding that 'when' expressions must be exhaustive to compile.
#2Using 'when' without an 'else' branch when cases are not exhaustive.
Wrong approach:val x = 10 val result = when (x) { 1 -> "One" 2 -> "Two" // No else branch }
Correct approach:val x = 10 val result = when (x) { 1 -> "One" 2 -> "Two" else -> "Other" }
Root cause:Misunderstanding exhaustiveness requirements for non-enum or open types.
#3Trying to use 'when' as a statement but expecting a return value.
Wrong approach:when (x) { 1 -> "One" 2 -> "Two" } val result = x // result is not assigned from when
Correct approach:val result = when (x) { 1 -> "One" 2 -> "Two" else -> "Other" }
Root cause:Confusing 'when' statement usage with expression usage.
Key Takeaways
'When' in Kotlin is a versatile expression that evaluates conditions and returns values, making code concise and readable.
It supports multiple conditions per branch, type checking with smart casts, and requires exhaustiveness when used as an expression.
Understanding how 'when' compiles helps write efficient and safe code, especially with enums and sealed classes.
Avoid common mistakes like missing cases or confusing statement vs expression usage to prevent bugs and compiler errors.
Mastering 'when' unlocks powerful Kotlin patterns for clean decision-making and safer code.

Practice

(1/5)
1. What does the when expression in Kotlin return when used as an expression?
easy
A. It returns a value based on the matched case.
B. It always returns Unit (no value).
C. It returns a Boolean indicating if a case matched.
D. It throws an exception if no case matches.

Solution

  1. Step 1: Understand when as expression

    In Kotlin, when can be used as an expression that returns a value depending on which case matches.
  2. Step 2: Compare with other options

    It does not always return Unit, nor a Boolean, and it requires an else branch to avoid exceptions, so it won't throw by default.
  3. Final Answer:

    It returns a value based on the matched case. -> Option A
  4. Quick Check:

    when returns value [OK]
Hint: Remember: when returns the matched case value [OK]
Common Mistakes:
  • Thinking when always returns Unit
  • Confusing when with if returning Boolean
  • Forgetting to add an else branch
2. Which of the following is the correct syntax to use when as an expression returning a value in Kotlin?
easy
A. val result = when x { 1 -> "One"; else -> "Other" }
B. val result = when (x) { x > 0 -> "Positive" else -> "Non-positive" }
C. val result = when { x > 0 -> "Positive"; else -> "Non-positive" }
D. val result = when (x) { in 1..10 -> "Small"; else -> "Large" }

Solution

  1. Step 1: Check correct when syntax with argument

    val result = when (x) { in 1..10 -> "Small"; else -> "Large" } uses when (x) with cases separated by semicolons and an else branch, which is correct.
  2. Step 2: Identify syntax errors in other options

    val result = when { x > 0 -> "Positive"; else -> "Non-positive" } uses semicolons inside braces correctly; val result = when (x) { x > 0 -> "Positive" else -> "Non-positive" } misses semicolon before else; val result = when x { 1 -> "One"; else -> "Other" } misses parentheses around x.
  3. Final Answer:

    val result = when (x) { in 1..10 -> "Small"; else -> "Large" } -> Option D
  4. Quick Check:

    Correct when syntax uses parentheses and semicolons [OK]
Hint: Use parentheses around variable and semicolons between cases [OK]
Common Mistakes:
  • Omitting parentheses around the variable
  • Using commas instead of semicolons
  • Missing semicolon before else branch
3. What is the output of the following Kotlin code?
val x = 5
val result = when {
  x < 0 -> "Negative"
  x == 0 -> "Zero"
  x in 1..10 -> "Small"
  else -> "Large"
}
println(result)
medium
A. Small
B. Zero
C. Negative
D. Large

Solution

  1. Step 1: Evaluate conditions in order

    x = 5 is not less than 0, not equal to 0, but is in 1..10 range, so the third case matches.
  2. Step 2: Determine returned value

    The matched case returns "Small", so result is "Small".
  3. Final Answer:

    Small -> Option A
  4. Quick Check:

    5 in 1..10 = true, returns "Small" [OK]
Hint: Check conditions top to bottom; first true case returns value [OK]
Common Mistakes:
  • Assuming else branch runs for 5
  • Confusing equality and range checks
  • Ignoring order of conditions
4. Identify the error in this Kotlin code using when as an expression:
val x = 3
val result = when (x) {
  1 -> "One"
  2 -> "Two"
}
println(result)
medium
A. Incorrect variable name in when.
B. Missing else branch causes compilation error.
C. Semicolons missing between cases.
D. Cannot use when as expression.

Solution

  1. Step 1: Check completeness of when expression

    The when expression covers only 1 and 2, but x = 3 is not handled and no else branch is provided.
  2. Step 2: Understand Kotlin requirement for exhaustive when

    When used as an expression, when must be exhaustive, so missing else causes a compilation error.
  3. Final Answer:

    Missing else branch causes compilation error. -> Option B
  4. Quick Check:

    Exhaustive when needs else [OK]
Hint: Always add else if not all cases covered [OK]
Common Mistakes:
  • Ignoring missing else branch
  • Thinking semicolons are mandatory
  • Assuming when always compiles without else
5. You want to assign a grade based on a score using when as an expression. Which code correctly returns "A" for scores 90 and above, "B" for 80-89, "C" for 70-79, and "F" otherwise?
hard
A. val grade = when (score) { score >= 90 -> "A" score >= 80 -> "B" score >= 70 -> "C" else -> "F" }
B. val grade = when (score) { in 90..100 -> "A" in 80..89 -> "B" in 70..79 -> "C" else -> "F" }
C. val grade = when { score >= 90 -> "A" score >= 80 -> "B" score >= 70 -> "C" else -> "F" }
D. val grade = when { in 90..100 -> "A" in 80..89 -> "B" in 70..79 -> "C" else -> "F" }

Solution

  1. Step 1: Understand when with condition expressions

    val grade = when { score >= 90 -> "A" score >= 80 -> "B" score >= 70 -> "C" else -> "F" } uses when without argument and conditions like score >= 90, which is valid and clear for ranges.
  2. Step 2: Check other options for errors

    val grade = when (score) { in 90..100 -> "A" in 80..89 -> "B" in 70..79 -> "C" else -> "F" } is correct syntax but uses ranges; val grade = when (score) { score >= 90 -> "A" score >= 80 -> "B" score >= 70 -> "C" else -> "F" } incorrectly uses conditions inside when(score) which expects values, not conditions; val grade = when { in 90..100 -> "A" in 80..89 -> "B" in 70..79 -> "C" else -> "F" } uses in without variable, which is invalid.
  3. Final Answer:

    val grade = when { score >= 90 -> "A" score >= 80 -> "B" score >= 70 -> "C" else -> "F" } -> Option C
  4. Quick Check:

    Use when without argument for conditions [OK]
Hint: Use when without argument for condition checks [OK]
Common Mistakes:
  • Using conditions inside when(variable)
  • Omitting variable in range checks
  • Misplacing in keyword
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard