A candidate tries to use `break` inside a `forEach { }` lambda to stop iteration and it won't compile. Explain why, and what the correct labeled-jump mechanism is in that case versus a real loop.
answer
- break/continue = loops only (for/while/do-while)
- forEach { } is a function + lambda, not a loop
- return@forEach behaves like continue, not break
- No break equivalent for forEach
- Early stop: for+break, first/firstOrNull, any, takeWhile
basics
~20 sbreak and continue only work in real loops (for, while). forEach { } is a function taking a lambda, not a loop, so break won't compile there. Inside the lambda you can only return@forEach to skip the current item, which is like continue, not break.
solid answer
~40 s`break`/`continue` are loop constructs; they're only legal inside `for`, `while`, and `do-while` bodies. `forEach` is a higher-order function, and `{ ... }` is a lambda, not a loop body — so `break`/`continue` there is a compile error ("break and continue are only allowed inside a loop"). The closest in-lambda tool is a labeled return: `return@forEach`, which exits the current lambda invocation for that element — semantically like `continue`, advancing to the next element. There is **no** lambda equivalent of `break` that stops `forEach` early; to truly stop early you must use a real loop with `break`, or switch to an operator that short-circuits (`first`, `firstOrNull`, `any`, `takeWhile`, or a `for` over the collection). This is exactly why the `Returns at Labels` topic (`return@label`) is separate from labeled break/continue: lambdas use `return@`, loops use `break@`/`continue@`.
code
kotlin · 11 lines// Skip with continue-like semantics
(1..5).forEach {
if (it == 3) return@forEach // continue-like
println(it)
}
// Real early stop needs a loop or short-circuit operator
for (x in 1..5) {
if (x == 3) break
println(x)
}go deeper
Knows break/continue belong to loops and not to forEach.
Uses return@forEach correctly and recognizes it as continue-like.
Explains there is no break for forEach and offers short-circuiting operators or a real loop for early exit.
Articulates the language rationale: loops use break@/continue@, lambdas use return@, and guides API/style choices around it.
## Why `break` fails in `forEach` `break` and `continue` are **structural jump statements bound to loops**. The compiler only accepts them inside `for`, `while`, or `do-while`. A `forEach { }` call looks loop-like but is actually: ```kotlin collection.forEach { element -> /* lambda body */ } ``` That `{ ... }` is a **lambda passed to a function**, not a loop. So: ```kotlin list.forEach { if (it == 3) break // COMPILE ERROR: 'break' is only allowed inside a loop } ``` Kotlin even emits a hint suggesting an annotated `return`. ## The in-lambda tool: `return@forEach` Inside the lambda you can do a **labeled return** that returns from the lambda for the current element: ```kotlin list.forEach { if (it == 3) return@forEach // skip this element -> behaves like continue println(it) } ``` `return@forEach` finishes the current lambda call and lets `forEach` move to the next element. It is **continue-like**, not break-like — it cannot stop the iteration. (The label `@forEach` is the implicit label of the lambda passed to `forEach`; this is the `Returns at Labels` mechanism, distinct from `break@`/`continue@`.) ## There is no `break` for `forEach` To actually **stop early**, choose one of: ```kotlin // 1. Real loop with real break for (x in list) { if (x == 3) break println(x) } // 2. Short-circuiting operators list.takeWhile { it != 3 }.forEach(::println) val hit = list.firstOrNull { it == 3 } if (list.any { it == 3 }) { /* ... */ } ``` `takeWhile`, `first`/`firstOrNull`, `any`, `none`, and `find` all stop at the first satisfying element, giving true early termination without any jump keyword. ## Summary table | Context | Skip current | Stop early | |---------|--------------|-----------| | `for`/`while` loop | `continue` (or `continue@label`) | `break` (or `break@label`) | | `forEach { }` lambda | `return@forEach` | not possible — use a loop or short-circuit operator | ## Why two mechanisms exist Loops are language control structures, so they get `break`/`continue` with optional labels to target outer loops. Lambdas are values; the only way to leave one early is to *return from it*, hence `return@label`. Keeping them separate avoids ambiguity about what a jump targets.
- Is `return@forEach` a break or a continue?Continue-like: it ends the lambda for the current element only and lets forEach proceed to the next element. It cannot stop the iteration.
- Name an operator that gives true early termination over a collection without a loop.first/firstOrNull, find, any, none, or takeWhile — each short-circuits at the first matching element.
saying these in an interview costs you the question
- Claiming break works inside forEach
- Saying return@forEach stops the whole iteration like break
- Not knowing first/any/takeWhile short-circuit
- Confusing forEach with a real for loop
- Suggesting an exception to break out of forEach