How do you write a function that RETURNS a function in Kotlin, and what is captured when the returned lambda references the enclosing function's parameters?
answer
- Return type is a function type: (Int) -> Int
- Returned lambda = closure over enclosing scope
- Each call => fresh captured binding
- Kotlin can capture+mutate var (Ref box)
- Basis for partial application / factories
basics
~10 sGive the function a function-type return, like (Int) -> Int, and return a lambda. The lambda remembers (captures) the outer variables it uses, so each call can make a customized function.
solid answer
~40 sDeclare the return type as a function type, e.g. fun adder(base: Int): (Int) -> Int = { x -> x + base }. The returned lambda is a closure: it captures the variable base by reference to the surrounding scope, keeping it alive after adder returns. Each invocation of adder produces a distinct function value bound to its own base. Unlike Java, Kotlin closures can capture and even mutate var locals (the compiler boxes a captured var in a Ref wrapper). You return the lambda directly, a function reference, or a stored value of the right type. Callers store it (val add5 = adder(5)) and invoke later: add5(10) == 15. This underlies currying/partial-application idioms and factory-style APIs.
code
kotlin · 8 linesfun multiplier(factor: Int): (Int) -> Int = { it * factor }
fun main() {
val double = multiplier(2)
val triple = multiplier(3)
println(double(10)) // 20
println(triple(10)) // 30 - independent captured factor
}go deeper
Can write a factory that returns a lambda and call the result later.
Explains closures and per-call capture, and the val/var capture difference vs Java.
Describes the Ref-boxing mechanism for mutable capture and memory/lifetime implications.
Weighs closure allocation cost, captured-state lifetimes/leaks, and when to prefer classes or inline.
## Returning a function To return a function, make the **return type** a function type and produce a value of that type: ```kotlin fun adder(base: Int): (Int) -> Int { return { x -> x + base } } // expression-body form: fun adder(base: Int): (Int) -> Int = { x -> x + base } ``` `adder(5)` does not add anything yet — it returns a **new function value** that, when later called, adds 5. ## Closures and capture The returned lambda `{ x -> x + base }` references `base`, a parameter of the *enclosing* `adder`. The lambda **captures** `base` — it closes over the enclosing scope. This is called a **closure**. The captured binding stays alive even after `adder` has returned: ```kotlin val add5 = adder(5) // base=5 captured val add10 = adder(10) // separate base=10 captured add5(1) // 6 add10(1) // 11 ``` Each call to `adder` yields an independent function value with its own captured `base`. ## Capturing `val` vs `var` - A captured **`val`** is read-only; the lambda just reads it. - Unlike Java (which only allows *effectively final* captures), Kotlin lets a lambda capture and **mutate a `var`**. The compiler implements this by boxing the variable in a hidden `Ref` object (e.g. `Ref.IntRef`) shared between the outer scope and the lambda: ```kotlin fun counter(): () -> Int { var n = 0 return { n++; n } // mutates captured var via a Ref box } val c = counter(); c(); c(); c() // 1, 2, 3 ``` ## What can you return? Anything assignable to the declared function type: - a lambda `{ ... }`, - a function reference `::someTopLevelFun`, - a stored function value passed through. ## Why it matters Returning functions is the foundation of **partial application / currying** idioms and **factory** functions that pre-bake configuration, producing reusable specialized callables.
- How does Kotlin let a lambda mutate a captured var when Java cannot?The compiler boxes the var in a shared Ref wrapper (e.g. Ref.IntRef); both the enclosing frame and the lambda read/write the same box.
- Do two calls to adder share the same captured base?No. Each invocation creates a new closure with its own captured copy of the parameter binding.
adder(5) is a vending machine pre-loaded with the number 5; press it later with any input and it dispenses input+5.
saying these in an interview costs you the question
- Saying the returned lambda runs immediately instead of being a deferred value
- Claiming Kotlin cannot capture mutable variables (confusing it with Java)
- Thinking all closures from one factory share mutable state
- Forgetting to declare the function-type return and returning a plain value