Scope Functions Workbook


Practice problems for let, run, apply, also, with. 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.

the two questions

1. Configure and return

Create a StringBuilder, append "a" and "b", and keep the builder — using the scope function meant for configuration.

Show answer Hide answer
val sb = StringBuilder().apply {
    append("a")
    append("b")
}

apply: receiver is this, returns the object.

2. Do this if not null

Given name: String?, send a welcome to it only when it isn’t null.

Show answer Hide answer
name?.let { sendWelcome(it) }

let: object is it, returns the block’s result.

3. Side effect in a chain

Given loadUser(), log the user and return it unchanged, in one chained call.

Show answer Hide answer
loadUser().also { println("loaded $it") }

also: object is it, returns the object.

4. Compute from members

Given a rectangle with width and height, compute its area with a scope function that exposes the object as this and returns the result.

Show answer Hide answer
val area = rectangle.run { width * height }

5. Group operations on one object

Given canvas, call drawLine(...) and drawCircle(...) on it without repeating canvas, using the non-extension form.

Show answer Hide answer
with(canvas) {
    drawLine(0, 0, 10, 10)
    drawCircle(5, 5, 3)
}

takeIf and choosing

6. Keep it only if it qualifies

Given input: String, return it only if it’s not blank, otherwise return from the function.

Show answer Hide answer
val value = input.takeIf { it.isNotBlank() } ?: return

takeIf returns the object or null, so it chains with Elvis.

7. Keep unless

Given input: String, return it unless it’s blank (in which case null), using a single scope function.

Show answer Hide answer
input.takeUnless { it.isBlank() }

takeUnless is takeIf’s negation — it keeps the object only when the condition is false.

8. Build and assign

Create a mutableListOf<Int>(), add 1 and 2 to it, and assign the resulting list to nums — using the scope function that returns the object.

Show answer Hide answer
val nums = mutableListOf<Int>().apply {
    add(1)
    add(2)
}

apply returns the object (the list), so the whole expression is assignable; also is its it-based counterpart.

9. Swap this for it

Rewrite rectangle.run { width * height } using let instead, so the object is referred to as it.

Show answer Hide answer
rectangle.let { it.width * it.height }

run exposes the object as this; let exposes it as it.

10. Combine two in a chain

Given a fresh Request(url), set its method = "POST" and then log it — using apply then also in a single chain that ends holding the request.

Show answer Hide answer
val request = Request(url)
    .apply { method = "POST" }
    .also { println("prepared $it") }

apply configures via this; also runs a side effect via it. Both return the object, so the chain ends with the request.


Back to the lesson, let, run, apply, also, with, or on to the next one: operator overloading.

Comments