Lambdas Workbook (Part 5): inline and Receivers
Practice problems for Why Lambdas Are Free, and Lambdas That Read Like Syntax. Each takes a minute or two. Write your own answer first, then click Show answer — nothing here is a trick question, just direct practice of the syntax from the lesson.
inline
1. Mark it inline
Make this higher-order function’s lambda cost nothing at runtime:
fun runTwice(block: () -> Unit) { block(); block() }
Show answer Hide answer
inline fun runTwice(block: () -> Unit) { block(); block() } 2. What inlining produces
Given inline fun repeatTimes(n: Int, action: (Int) -> Unit) { for (i in 0 until n) action(i) }, write the code that repeatTimes(2) { println(it) } effectively becomes after inlining.
Show answer Hide answer
for (i in 0 until 2) println(i)No lambda object, no extra call — the body is copied in.
3. reified
Write inline fun <reified T> Any.asOrNull(): T? returning the receiver as a T, or null on a mismatch.
Show answer Hide answer
inline fun <reified T> Any.asOrNull(): T? = this as? Treified keeps T at runtime; it works only because the function is inline.
4. noinline
In inline fun run2(a: () -> Unit, b: () -> Unit), mark b so it is not inlined (so you can store it in a variable).
Show answer Hide answer
inline fun run2(a: () -> Unit, noinline b: () -> Unit) {
a()
val saved = b
saved()
} lambdas with a receiver
5. A receiver lambda type
Declare val build of type StringBuilder.() -> Unit whose body appends "hi".
Show answer Hide answer
val build: StringBuilder.() -> Unit = { append("hi") }The StringBuilder. prefix makes this inside the lambda a StringBuilder, so append needs no qualifier.
6. Configure with apply
Use apply to create a StringBuilder, append "a" then "b", and keep the builder.
Show answer Hide answer
val sb = StringBuilder().apply {
append("a")
append("b")
} 7. buildString
Use buildString to assemble "Hello, world".
Show answer Hide answer
val text = buildString {
append("Hello, ")
append("world")
} 8. apply returns the object
Configure a File("out.txt") by calling createNewFile() via apply, assigning the resulting File to f.
Show answer Hide answer
val f = File("out.txt").apply { createNewFile() }apply returns the receiver, so the whole expression is the configured File.
your own receiver builder
9. A receiver-lambda function
Write buildInts(block: MutableList<Int>.() -> Unit): List<Int> that creates a list, applies the block to it, and returns it.
Show answer Hide answer
fun buildInts(block: MutableList<Int>.() -> Unit): List<Int> {
val list = mutableListOf<Int>()
list.block()
return list
} 10. Use your builder
Using buildInts, build the list [1, 2, 3] — calling add without any prefix.
Show answer Hide answer
buildInts {
add(1)
add(2)
add(3)
}Inside the block the receiver is the MutableList, so add resolves to this.add.
11. Why the bare calls work
In buildInts { add(10) }, what is add actually being called on, and why don’t you write it explicitly?
Show answer Hide answer
buildInts {
this.add(10) // 'this' is the MutableList — the receiver
add(10) // identical: the receiver is implicit
}A receiver lambda makes the receiver this, and this. is optional — exactly like inside a member function.
Back to the lesson, Why Lambdas Are Free. That completes the lambda series — next in the curriculum: classes.
Comments