What is the difference between a lambda, an anonymous function, and a callable (function/property) reference in Kotlin, and when would you use each?
answer
- lambda = { }, last expr is result, `it`
- anon fun = explicit return type + local return
- ::name reference forwards to existing code
- bound ref captures receiver: obj::method
- property ref gives get/set
basics
~20 sAll three produce a function value. A lambda is the short { } form. An anonymous function uses fun(...) {...} with an explicit return type. A reference like ::foo points at existing code instead of rewriting it.
solid answer
~50 sA lambda `{ a, b -> a + b }` is the most concise way to write inline behavior; `it` names the single parameter and the last expression is the result. An anonymous function `fun(a: Int): Int { return a * 2 }` is useful when you need an explicit return type or a local `return` that exits only the function (a lambda's bare `return` exits the enclosing function unless labeled). A callable reference points at something that already exists: a function reference `::toInt` / `String::length`, a bound reference `instance::method`, or a property reference `Person::name` (also gives a getter/setter). References avoid wrapping in a trivial lambda and improve readability when forwarding to existing logic. All three become `FunctionN` values assignable to the same function type, so they're interchangeable at call sites like `map`, `filter`, or callbacks.
code
kotlin · 8 linesdata class Person(val name: String, val age: Int)
val people = listOf(Person("Ann", 30), Person("Bob", 25))
// property reference instead of { it.age }
val byAge = people.sortedBy(Person::age)
// function reference instead of { it.uppercase() }
val names = people.map(Person::name).map(String::uppercase)
println(byAge); println(names)go deeper
Recognizes lambda syntax and that ::foo references a function.
Distinguishes all three forms and their return-semantics and receiver-binding differences.
Explains non-local vs local return, bound references, property references with get/set, and interchangeability as FunctionN values.
Advises on API readability/maintainability tradeoffs (references vs lambdas) and pitfalls of non-local returns in inlined HOFs.
## The three forms Kotlin gives three ways to produce a **function value** (an object you can pass around): ### 1. Lambda expression ```kotlin val add: (Int, Int) -> Int = { a, b -> a + b } list.filter { it > 0 } // `it` = the single implicit parameter ``` - Body in `{ }`; the **last expression** is the return value (no `return` keyword needed). - Single parameter can be referred to implicitly as **`it`**. - A bare `return` inside a lambda is a **non-local return** — it returns from the enclosing *function*, not the lambda. Use a **label** (`return@filter`) to return just from the lambda. ### 2. Anonymous function ```kotlin val add = fun(a: Int, b: Int): Int { return a + b } ``` - Looks like a normal `fun` but has no name. - Lets you **declare an explicit return type** and use a normal local `return` that exits only this function. - Cannot use `it`; parameters must be named. ### 3. Callable references (`::`) ```kotlin val parse = String::toInt // unbound: receiver supplied at call val len = "hi"::length // bound: receiver fixed (a property ref here is a getter) val ctor = ::Person // constructor reference val name = Person::name // property reference (KProperty: has get/set) ``` - **Function reference** `::foo` / `Type::foo` points at an existing function. - **Bound reference** `obj::foo` captures the receiver instance. - **Property reference** exposes `get()` (and `set()` for `var`), useful in `sortedBy`, etc. - **Constructor reference** `::Type` acts as a factory function. ## Choosing between them | Need | Use | |------|-----| | Short inline behavior | lambda | | Explicit return type / local `return` | anonymous function | | Forward to an existing function/property | reference | ## They are interchangeable as values All three implement the appropriate `FunctionN` interface, so any of them fits a parameter typed `(String) -> Int`: ```kotlin fun apply(f: (String) -> Int) = f("hello") apply { it.length } // lambda apply(String::length) // reference apply(fun(s: String) = s.length) // anonymous fun ```
- Why might you pick an anonymous function over a lambda for a callback?Because its bare `return` exits only that function and you can state an explicit return type, avoiding accidental non-local returns from the enclosing function.
- What does a property reference like Person::name give you beyond a getter?It is a KProperty; for a var it also exposes set(), and it carries metadata (name), so it works with reflection-aware APIs.
saying these in an interview costs you the question
- Claiming a lambda's `return` exits only the lambda by default
- Saying anonymous functions and lambdas are identical in return semantics
- Not knowing references can be bound to an instance (obj::method)
- Thinking ::Person is invalid (it is a constructor reference)
- Using a wrapper lambda { it.length } where String::length suffices, then claiming you can't reference it