What is a higher-order function in Kotlin? Show how to write one that takes a function as a parameter and one that returns a function.
answer
- HOF: takes and/or returns a function
- param typed (T) -> R, call f(x) inside
- returning a function = closure capturing locals
- trailing lambda goes outside the parens
- inline removes FunctionN overhead
basics
~10 sA higher-order function takes a function as an argument, returns a function, or both. For example, map takes a transform function. You declare the parameter with a function type and call it inside.
solid answer
~40 sA higher-order function (HOF) either accepts a function value as a parameter or returns one. You declare such a parameter with a function type: `fun <T, R> transform(xs: List<T>, f: (T) -> R): List<R>`, then call `f(x)` inside. Returning a function means the return type is a function type: `fun multiplier(by: Int): (Int) -> Int = { it * by }` — this captures `by` to build a closure. Callers pass lambdas, anonymous functions, or references, and Kotlin's trailing-lambda syntax lets the last function argument move outside the parentheses: `transform(xs) { it.uppercase() }`. HOFs are the backbone of the stdlib (`map`, `filter`, `fold`, `let`, `apply`) and of DSLs. Marking a HOF `inline` removes the FunctionN allocation and enables non-local returns and reified type parameters.
code
kotlin · 6 linesfun applyTwice(x: Int, op: (Int) -> Int): Int = op(op(x))
fun adder(delta: Int): (Int) -> Int = { it + delta }
println(applyTwice(5) { it * 2 }) // 20
val addTen = adder(10)
println(addTen(1)) // 11go deeper
Can use stdlib HOFs like map/filter and pass a lambda.
Writes a HOF that takes a function param and one that returns a function (closure), and uses trailing-lambda syntax.
Explains closures over captured state, composition, and the inline performance angle plus non-local return/reified enablement.
Designs HOF-based APIs/DSLs with clear function-type signatures and considers inline cost/benefit at the boundary.
## Definition A **higher-order function (HOF)** is a function that does at least one of: - **takes a function** as a parameter, or - **returns a function** as its result. This is possible because Kotlin functions are first-class values typed with **function types** like `(T) -> R`. ## Taking a function parameter ```kotlin fun <T, R> myMap(xs: List<T>, f: (T) -> R): List<R> { val out = ArrayList<R>(xs.size) for (x in xs) out.add(f(x)) // call the passed-in function return out } val lengths = myMap(listOf("a", "bb")) { it.length } // [1, 2] ``` - The parameter `f` has a **function type**. - Inside, you invoke it with `f(x)` (sugar for `f.invoke(x)`). ### Trailing-lambda syntax If the **last** parameter is a function type, the lambda can go **outside** the parentheses; if it's the only argument you can drop the parentheses entirely: ```kotlin xs.filter { it > 0 } ``` ## Returning a function (closures) ```kotlin fun multiplier(by: Int): (Int) -> Int = { n -> n * by } val triple = multiplier(3) println(triple(10)) // 30 ``` The returned lambda **captures** `by` from the enclosing scope — this is a **closure**. Each call to `multiplier` produces a new function value bound to its own `by`. ## Composition Because functions are values, you can combine them: ```kotlin fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C = { a -> f(g(a)) } val shout = compose(String::uppercase) { s: String -> "$s!" } println(shout("hi")) // "HI!" ``` ## Where you already use them `map`, `filter`, `fold`, `sortedBy`, `forEach`, scope functions (`let`, `run`, `apply`, `also`, `with`), and DSL builders are all HOFs. ## Performance note A HOF passes a `FunctionN` object and calls it virtually. Marking the HOF **`inline`** copies bodies into the call site, removing that overhead and enabling **non-local returns** and **`reified`** type parameters.
- Why does returning a lambda from a function create a closure?The returned lambda references variables from the enclosing scope, so the compiler captures them into the function object, keeping them alive after the outer function returns.
- When can you drop the parentheses entirely at a HOF call site?When the function-typed parameter is the only argument, e.g. xs.filter { it > 0 }; otherwise the trailing lambda just moves outside the parentheses.
A higher-order function is a manager: it doesn't do the task itself but accepts a worker (function) to delegate to, or hands you back a configured worker to use later.
saying these in an interview costs you the question
- Defining HOF only as 'takes a function', forgetting 'returns a function'
- Not knowing the parameter must be declared with a function type
- Confusing trailing-lambda syntax with a language-only quirk rather than last-param rule
- Saying returned lambdas don't capture enclosing state
- Believing HOFs always allocate even when inline