Why can't you write `val b = (a = 5)` or use an assignment/loop as a value in Kotlin?
answer
- assignments & loops are statements => no value (Unit)
- val b = (a = 5) won't compile
- design choice: kills `if (a = b)` vs `==` bug
- need a value from a loop -> sequences/ranges/first/repeat
- while + readLine ?: break replaces C's assign-in-condition
basics
~20 sIn 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 sKotlin 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 linesvar 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
Knows you can't assign the result of a = 5 or a loop to a variable.
Explains assignments and loops are statements typed Unit and gives a sequence/range-based alternative.
Frames it as a deliberate design choice preventing =/== bugs and fluently rewrites assign-in-condition loops functionally.
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