What does `return@map` do, and how does it differ from a bare `return` inside a lambda passed to map?
answer
- Bare return = non-local, exits the fun
- return@map = local, exits the lambda
- Implicit label = function name
- return@forEach behaves like continue
- Non-local return needs an inline function
basics
~10 sreturn@map exits just the current lambda call and supplies that element's result, like 'continue' for the iteration. A bare return would try to exit the whole surrounding function instead.
solid answer
~40 sInside a lambda, a **bare `return` is a non-local return**: it returns from the nearest enclosing *named function*, not from the lambda. To return from the lambda itself you use a **qualified return** with an implicit label named after the function the lambda is passed to: `return@map value`. For each invocation of the `map` lambda, `return@map x` makes `x` that element's mapped result and skips the rest of the lambda body. This is essential when you have early-exit logic in a multi-statement lambda. You can also label a lambda explicitly: `list.map loop@ { return@loop x }`. Bare `return` is only legal inside lambdas of **inline** functions (like `map`, `forEach`, `let`); for non-inline lambdas it is a compile error, forcing the qualified form.
code
kotlin · 5 linesval out = listOf(1, 2, 3, 4).map { n ->
if (n % 2 == 0) return@map -1
n * n
}
// out == [1, -1, 9, -1]go deeper
Knows return@map exits the lambda and bare return is different.
Explains non-local vs local return and that the label defaults to the function name.
Ties legality of bare return to inline functions and explains continue-like semantics plus explicit labels for nesting.
Reasons about why non-inline lambdas forbid non-local returns (lifetime/escape), and weighs readability of early-return lambdas vs functional alternatives.
## Two kinds of return inside a lambda ### 1. Bare `return` = non-local return A `return` with no label returns from the **nearest enclosing `fun`**, jumping out past the lambda entirely. This only compiles when the lambda is an argument to an **inline** function (the lambda body is inlined into the caller, so the JVM `return` is meaningful): ```kotlin fun findFirstEven(nums: List<Int>): Int? { nums.forEach { n -> if (n % 2 == 0) return n // returns from findFirstEven, not from forEach } return null } ``` ### 2. Qualified `return@label` = local return `return@map` returns from the **lambda invocation itself**. The implicit label is the name of the function the lambda is passed to (`map`, `filter`, `let`, `run`, `forEach`...). It supplies the value for the current element and continues iteration: ```kotlin val result = listOf(1, 2, 3, 4).map { n -> if (n % 2 == 0) return@map 0 // even -> 0, keep going val squared = n * n squared // odd -> n*n } // result == [1, 0, 9, 0] ``` ## Explicit labels You can name a lambda yourself, which is required if the implicit name is ambiguous or you nest lambdas: ```kotlin listOf(1, 2, 3).forEach outer@ { listOf(10, 20).forEach { inner -> if (inner == 20) return@outer // skip rest of OUTER lambda for this element } } ``` ## `return@map` vs continue/break - `return@forEach` behaves like **`continue`** — it ends the current iteration's lambda body and moves on. - There is no direct lambda equivalent of `break`; use a real loop, `takeWhile`, `first { }`, or a non-local `return`. ## Inline matters For a **non-inline** functional parameter, a bare `return` is illegal (the lambda may outlive the function), so you must use a qualified `return@label`. The standard collection operators (`map`, `filter`, `forEach`) and scope functions (`let`, `run`, `apply`, `also`, `with`) are all `inline`, so both forms are available there.
- Why can't you use a bare return in a lambda passed to a non-inline higher-order function?The lambda could be stored and called after the enclosing function returns, so a non-local return would be meaningless. The compiler rejects it; you must use return@label.
- How would you simulate break inside a forEach?Use a non-local return from the enclosing function, or restructure with first { }, takeWhile, or an indexed/explicit loop.
Bare return is the building's fire exit (you leave the whole building); return@map is just stepping out of the current room and back into the hallway.
saying these in an interview costs you the question
- Claiming bare return exits only the lambda
- Not knowing the label defaults to the function name
- Thinking return@map works in any function regardless of inline
- Confusing return@forEach (continue) with break
- Using bare return to mean 'skip this element'