How do you declare a receiver type on an anonymous function, and how does an anonymous function help with overload resolution where a lambda would be ambiguous?
answer
- fun Receiver.(p): R { } gives a receiver
- this = receiver inside the body
- anon fun pins param types -> resolves overloads
- lambda relies on target typing -> can be ambiguous
- explicit return type can disambiguate generics
basics
~20 sYou can write fun Foo.(x: Int): Int { ... } to give an anonymous function a receiver, producing a function-with-receiver type. Because anonymous functions state parameter and return types explicitly, they can resolve overloads that a bare lambda leaves ambiguous.
solid answer
~40 sAn anonymous function can declare a **receiver** just like an extension function: fun Foo.(x: Int): Int { ... } has type Foo.(Int) -> Int, where inside the body this refers to the Foo receiver. This lets you build a value of a function-with-receiver type explicitly. The second benefit is **overload resolution**: when a function is overloaded with different functional parameter types — say accept((Int) -> Unit) and accept((String) -> Unit) — passing a lambda { ... } may be ambiguous because its parameter type is inferred from context. An anonymous function pins the types: accept(fun(x: Int) {}) unambiguously selects the (Int) -> Unit overload. The explicit signature removes the inference guesswork. Anonymous functions also let you specify a return type the lambda would otherwise have to infer, which occasionally matters for resolving generic overloads.
code
kotlin · 6 linesfun handle(cb: (Int) -> Unit) = cb(1)
fun handle(cb: (String) -> Unit) = cb("x")
// handle { println(it) } // ERROR: ambiguous overload
handle(fun(n: Int) { println("int $n") }) // picks (Int) -> Unit
handle(fun(s: String) { println("str $s") }) // picks (String) -> Unitgo deeper
May not know receivers or overload-ambiguity scenarios; can at most recall the fun Foo.() syntax.
Knows the receiver syntax and that explicit types can disambiguate, with shaky reasoning about why.
Explains target typing vs explicit signatures and deliberately uses anonymous functions to resolve ambiguity.
Designs APIs to avoid forcing such ambiguity and weighs receiver-typed literals against DSL readability.
## Receivers on anonymous functions Kotlin supports **function types with a receiver**, written `Receiver.(Params) -> Result`. Inside such a function `this` is the receiver. You can construct one with an anonymous function by putting the receiver before the parameter list, exactly like an extension function: ```kotlin val build: StringBuilder.(String) -> Unit = fun StringBuilder.(s: String) { append(s) // 'this' is the StringBuilder receiver append('!') } val sb = StringBuilder() sb.build("hi") // called with receiver syntax println(sb) // hi! ``` A lambda can also target a receiver type (the compiler infers it from the expected type), but the anonymous-function form lets you state `StringBuilder.(...)` **explicitly** at the literal itself. ## Overload resolution: the headline use Consider overloads that differ only in their functional parameter: ```kotlin fun accept(handler: (Int) -> Unit) { /* ... */ } fun accept(handler: (String) -> Unit) { /* ... */ } ``` A lambda is ambiguous because its parameter type is inferred *from the expected type*, and both overloads supply one: ```kotlin accept { x -> println(x) } // ERROR: overload ambiguity ``` An anonymous function carries its own explicit parameter type, so resolution is unambiguous: ```kotlin accept(fun(x: Int) { println(x) }) // selects (Int) -> Unit accept(fun(x: String) { println(x) }) // selects (String) -> Unit ``` The explicit `: ReturnType` can likewise disambiguate overloads that differ by result type when combined with generics. ## Why this works Lambdas rely on **target typing**: the expected type drives inference of their parameter and return types. When multiple targets are equally valid, the lambda has nothing to commit to and the call is ambiguous. An anonymous function is a fully typed literal — its signature is known independently of context — so the compiler can match it against exactly one overload. ## Practical guidance Reach for an anonymous function when: - you need a receiver stated explicitly at the literal, or - a lambda triggers an overload-ambiguity error, or - you want an explicit return type for clarity or generic resolution. Otherwise prefer the more concise lambda. Both still compile to the same underlying `Function`/`FunctionN` types.
- Can a lambda target a receiver type at all?Yes, when the expected type is a function-with-receiver type the compiler binds 'this'; but the anonymous-function form lets you write the receiver explicitly at the literal.
- Besides overloads, when else does explicit typing on an anonymous function help?When the surrounding context can't infer parameter types (e.g. a generic position with no other constraints) or when you want a declared return type for readability.
A lambda asks 'what type did you expect?'; an anonymous function declares its type up front, so the compiler never has to guess between overloads.
saying these in an interview costs you the question
- Claiming anonymous functions can't have receivers
- Saying lambdas are never ambiguous in overload resolution
- Confusing receiver (this) with a regular first parameter
- Thinking the two forms compile to different runtime types
- Overusing anonymous functions where a concise lambda is clearer