What does the :: operator do when applied to a function name, e.g. `::println` or `String::length`, and what is the resulting value?
answer
- :: = reference, not call
- Result is KFunction (also a (P)->R)
- ::topLevel has no receiver
- Type::member leaves receiver as first param
- Pass where a lambda is expected
basics
~20 sThe :: operator turns a named function into a value you can store in a variable or pass to another function, instead of calling it. The result is a function object you can invoke later.
solid answer
~30 s`::` creates a callable reference: it takes a declared `fun` and produces a first-class value implementing the `KFunction` interface (a subtype of the matching `FunctionN` type). `::println` references a top-level function; `String::length` references a member with the receiver still unbound (it becomes the first parameter). You can store the reference in a `val`, pass it where a lambda is expected (`list.map(String::length)`), and invoke it with `()`. It's the function-reference equivalent of a lambda but points at an existing declaration, so it avoids wrapping the call in `{ it.length }`.
code
kotlin · 8 linesfun square(x: Int) = x * x
fun main() {
val f: (Int) -> Int = ::square // reference, not invoked
println(f(5)) // 25 — invoked here
println(listOf(1, 2, 3).map(::square)) // [1, 4, 9]
println(listOf("a", "bb").map(String::length)) // [1, 2]
}go deeper
Knows :: makes a function into a passable value and can use list.map(::fn).
Explains the KFunction result type and that Type::member leaves the receiver unbound as the first parameter.
Discusses overload resolution of references and reflection metadata carried by KFunction.
Frames references vs lambdas in terms of API ergonomics, reflection cost, and binary compatibility of exposed signatures.
## What `::` is The double-colon `::` is Kotlin's **callable reference** operator. Instead of *calling* a function, it produces a **value that represents the function** — a first-class object you can store, pass, and invoke later. ```kotlin fun greet(name: String) = "Hi $name" val ref = ::greet // a value, NOT a call val msg = ref("Ada") // invoke later -> "Hi Ada" ``` ## The type produced The reference is an instance of **`KFunction`** (from `kotlin.reflect`), which also implements the ordinary function type `(P...) -> R`. So `::greet` has type `KFunction1<String, String>` and is usable anywhere a `(String) -> String` is expected: ```kotlin val names = listOf("Ada", "Linus") val msgs = names.map(::greet) // ["Hi Ada", "Hi Linus"] ``` ## Top-level vs member references - `::println` — a **top-level** function reference; no receiver involved. - `String::length` — a **member/unbound** reference. The receiver (`String`) is *not* supplied, so it becomes the **first parameter**: the type is roughly `(String) -> Int`. ```kotlin listOf("a", "bb").map(String::length) // [1, 2]; each string is the receiver arg ``` ## Why use it instead of a lambda A reference points at an existing declaration, so `list.map(::greet)` is clearer and slightly cheaper than `list.map { greet(it) }`. It also carries reflection metadata (name, parameters) via the `KFunction` interface. ## Key terms - **Callable reference**: a value pointing at a declared function/property. - **`KFunction`**: the reflective type of that value; also a normal function type. - **Receiver**: the object a member function is called *on* (the `this`).
- Can you pass `::println` directly to `forEach`?Yes: `list.forEach(::println)`. `println` overloads on the argument type and Kotlin resolves the one matching the element type, producing a `(T) -> Unit` reference.
- What's the difference between `::greet` and `{ greet(it) }`?Both are usable as `(String)->String`. The reference points at the existing declaration and carries reflection metadata; the lambda is a fresh anonymous function wrapping the call.
A function reference is like saving someone's phone number (the reference) versus actually dialing it (the call) — you hold it now and dial later.
saying these in an interview costs you the question
- Thinking `::greet` calls the function immediately
- Saying the result is a String/return value rather than a function object
- Not knowing `String::length` makes the receiver the first parameter
- Confusing `::` with `.` member access
- Believing references only work with lambdas, not vals