Lambdas Workbook (Part 3): Closures
Practice problems for Closures: What a Lambda Remembers. 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 ideas from the lesson.
capturing
1. Capture a parameter
Write aboveThreshold(numbers: List<Int>, limit: Int) that returns the elements greater than limit — the lambda captures limit.
Show answer Hide answer
fun aboveThreshold(numbers: List<Int>, limit: Int) =
numbers.filter { it > limit } 2. Capture and mutate
Count how many strings in words are blank, using forEach and a captured var counter. (This mutation of a captured variable is exactly what Java forbids.)
Show answer Hide answer
var blanks = 0
words.forEach { if (it.isBlank()) blanks++ } 3. Sum without sum()
Total nums by capturing and updating a var inside forEach.
Show answer Hide answer
var total = 0
nums.forEach { total += it } stateful lambdas
4. A counter
Write counter(): () -> Int returning a lambda that yields 1, 2, 3, … on successive calls.
Show answer Hide answer
fun counter(): () -> Int {
var n = 0
return { ++n }
}The returned lambda keeps n alive after counter has returned.
5. A configured multiplier
Write multiplierOf(factor: Int): (Int) -> Int returning a lambda that multiplies its argument by the captured factor.
Show answer Hide answer
fun multiplierOf(factor: Int): (Int) -> Int = { it * factor }
val triple = multiplierOf(3)
triple(10) // 30 6. A remembered greeting
Write greeterFor(name: String): () -> String returning a lambda that greets the captured name.
Show answer Hide answer
fun greeterFor(name: String): () -> String = { "Hello, $name" } shared and looped capture
7. Two lambdas, one variable
Declare two lambdas, add and reset, that both operate on the same captured var total.
Show answer Hide answer
var total = 0
val add = { x: Int -> total += x }
val reset = { total = 0 }Both close over the same total, so changes through one are visible through the other.
8. Capture in a loop
Fill a list with three lambdas, each capturing the loop value i from 1..3, so calling them in turn prints 123.
Show answer Hide answer
val printers = mutableListOf<() -> Unit>()
for (i in 1..3) printers.add { print(i) }
printers.forEach { it() } // 123Each iteration’s i is a fresh binding, so every lambda keeps its own.
9. Collect into a captured list
Write a lambda collect that appends its Int argument to a captured MutableList<Int> named seen.
Show answer Hide answer
val seen = mutableListOf<Int>()
val collect = { x: Int -> seen.add(x) }
collect(1)
collect(2)
seen // [1, 2] 10. Tally into a captured map
Count word frequencies into a captured MutableMap<String, Int>, using forEach.
Show answer Hide answer
val freq = mutableMapOf<String, Int>()
words.forEach { freq[it] = freq.getOrDefault(it, 0) + 1 } 11. A counter with reset
Write makeCounter(): Pair<() -> Int, () -> Unit> returning two lambdas — next (yields 1, 2, 3, …) and reset (sets it back to 0) — that share one captured var.
Show answer Hide answer
fun makeCounter(): Pair<() -> Int, () -> Unit> {
var n = 0
val next = { ++n }
val reset = { n = 0 }
return next to reset
}Both returned lambdas close over the same n.
Back to the lesson, Closures: What a Lambda Remembers, or on to part four: references, returns, and anonymous functions.
Comments