androidengineers.Book a session

DSL Creation and Metaprogramming

Function Literals with Receiver

article15 minHard

Receiver lambdas expose a controlled vocabulary

A Builder.() -> Unit lambda makes builder members directly available inside a block. The caller still receives an ordinary function value; no special parser or runtime language is involved.

class Topics {
    private val items = mutableListOf<String>()
    fun add(title: String) { require(title.isNotBlank()); items.add(title) }
    fun snapshot(): List<String> = items.toList()
}

fun topics(block: Topics.() -> Unit): List<String> = Topics().apply(block).snapshot()

fun main() { check(topics { add("Kotlin") } == listOf("Kotlin")) }

The receiver limits the obvious operations offered by completion. Avoid exposing internal mutable collections, or callers can bypass validation and retain references after construction.

Exercise

Add a second operation that normalizes whitespace before adding a title, then compare whether a single consistently validating operation is clearer. Rewrite the block as an ordinary lambda taking a named builder parameter.

Check: receiver syntax should improve readability without changing the validation rules or copying behavior.

Reference: Receiver functions

YOUR LEARNING JOURNEY

0 of 110 available lessons completed

Progress saved in this browser. No account needed.
Function Literals with Receiver | Kotlin Core Programming | Android Engineers