Careeroza
Lambdas with Receivers
The Building Block of DSLs
A lambda with receiver has the type T.() -> R. Inside it, this is a T, so you can call T's members directly. This is how apply, buildString and Gradle's dependencies { } work.
Example
fun buildMessage(action: StringBuilder.() -> Unit): String {
val sb = StringBuilder()
sb.action() // sb becomes 'this' inside the lambda
return sb.toString()
}
fun main() {
val msg = buildMessage {
append("Hello, ")
append("Kotlin")
append("!")
}
println(msg)
// the standard library has the same thing
val receipt = buildString {
appendLine("Item: Coffee")
appendLine("Qty: 2")
append("Total: Rs 360")
}
println(receipt)
val ids = buildList { add(1); addAll(listOf(2, 3)); add(4) }
println(ids)
}Output
Hello, Kotlin! Item: Coffee Qty: 2 Total: Rs 360 [1, 2, 3, 4]
Function Type vs Receiver Type
| Type | Inside the lambda | Call it |
|---|---|---|
(StringBuilder) -> Unit | it.append("x") | block(sb) |
StringBuilder.() -> Unit | append("x") (implicit this) | sb.block() or block(sb) |