skip to content

Why can't you write `val b = (a = 5)` or use an assignment/loop as a value in Kotlin?

level: middleimportance: should knowfreq 35%

answer

  1. assignments & loops are statements => no value (Unit)
  2. val b = (a = 5) won't compile
  3. design choice: kills `if (a = b)` vs `==` bug
  4. need a value from a loop -> sequences/ranges/first/repeat
  5. while + readLine ?: break replaces C's assign-in-condition

basics

~20 s

In Kotlin, assignments and loops are statements, not expressions, so they don't produce a value you can store. That's why val b = (a = 5) doesn't compile and you can't use a for/while loop on the right side of =.

solid answer

~50 s

Kotlin deliberately makes **assignments** and **loops** statements, not expressions, so they yield no usable value. `val b = (a = 5)` does not compile because `a = 5` produces nothing (its type is `Unit` as a statement, and assignment isn't allowed in an expression slot at all). Similarly you cannot write `val x = while (...) {...}` or `val y = for (...) {...}` — loops always evaluate to `Unit`. This is a conscious design choice: C/Java allow `a = b = c` and `while ((line = read()) != null)`, a common source of `=` vs `==` bugs; Kotlin removes that footgun. To do the equivalent, assign separately, or use an expression construct (`if`/`when`/`try`) or a functional API (`generateSequence`, `takeWhile`, `repeat`, ranges) instead of a value-producing loop. Increment/decrement (`++`/`--`) are also statements in Kotlin in this sense — there's no value-returning pre/post-increment expression to chain.

code

kotlin · 7 lines
kotlin
var a = 0
// val b = (a = 5)         // ERROR: assignment is not an expression
a = 5; val b = a          // do it in two steps instead

// loops don't yield values; use functional tools:
val firstBig = (1..1000).first { it > 500 }
generateSequence(::readLine).forEach(::println)

go deeper

for a junior

Knows you can't assign the result of a = 5 or a loop to a variable.

for a middle

Explains assignments and loops are statements typed Unit and gives a sequence/range-based alternative.

for a senior

Frames it as a deliberate design choice preventing =/== bugs and fluently rewrites assign-in-condition loops functionally.

for a principal

Discusses expression-oriented language design tradeoffs and steers teams toward functional iteration that returns values cleanly.

## Statements that aren't expressions Kotlin makes a clear split. These are **statements** (no usable value): - **Assignments**: `a = 5`, `a += 1` — type is effectively `Unit`; assignment is not permitted in an expression position. - **Loops**: `for`, `while`, `do/while` — always evaluate to `Unit`. These are **expressions** (produce a value): `if`, `when`, `try`, function calls, literals. ## Why `val b = (a = 5)` fails In C/Java, `a = 5` *evaluates to* 5, enabling `b = a = 5` and `while ((x = next()) != null)`. Kotlin forbids assignment-as-expression: ```kotlin var a = 0 val b = (a = 5) // ERROR: assignments are not expressions ``` The payoff: you can't accidentally write `if (a = b)` when you meant `if (a == b)` — a classic C bug — because the assignment isn't a boolean (or any) value. ## Loops yield Unit ```kotlin val x = while (cond) { ... } // ERROR / Unit, never a useful value ``` If you want a *value* from iteration, use expression-oriented or functional tools instead: ```kotlin val firstEven = (1..100).first { it % 2 == 0 } val lines = generateSequence(::readLine).takeWhile { it.isNotBlank() }.toList() repeat(3) { println(it) } ``` ## Equivalent of `while ((line = read()) != null)` ```kotlin while (true) { val line = readLine() ?: break process(line) } // or, functionally: generateSequence(::readLine).forEach(::process) ``` ## Increments `a++` / `++a` mutate but Kotlin doesn't encourage chaining them as values in expression slots; treat them as statements. ## Key APIs/keywords statement vs expression, `Unit`, `generateSequence`, `takeWhile`, `repeat`, ranges `..`, `break`.

  • What real-world bug does forbidding assignment-as-expression prevent?
    The classic `if (a = b)` typo (assignment instead of `==`). In Kotlin that simply doesn't compile because assignment yields no boolean/value.
  • How do you replace `while ((line = reader.readLine()) != null)`?
    Use `while (true) { val line = reader.readLine() ?: break; ... }` or `generateSequence(reader::readLine).forEach { ... }`.

An assignment is like filing a form — it gets the job done but hands you no receipt to pass along.

saying these in an interview costs you the question

  • Claiming `a = 5` returns 5 in Kotlin like in Java
  • Trying to use a for/while loop on the right-hand side of `=`
  • Not knowing loops evaluate to Unit
  • Unable to give the functional/sequence replacement for value-producing loops
  • Confusing this with if/when/try, which ARE expressions

context