Returning Closures
Part of the Logic & Flow section of Coddy's Swift journey — lesson 41 of 56.
You saw makeCounter return a closure. The same trick lets you build configurable behaviour: take parameters once, get a function back that uses them many times.
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
let tenfold = multiplier(10)
print(triple(4)) // 12
print(tenfold(4)) // 40The returned closure captures k, so each multiplier(...) call produces a brand-new closure with its own k.
This pattern is the core of "strategy" code in Swift: write a function that takes a configuration and returns a closure, then pass the closure to map, filter, sorted(by:), or anywhere else a function-shaped value is expected.
Challenge
MediumBuild two closure factories:
greaterThan(_ k: Int) -> (Int) -> Bool: returns a predicate that'struewhen its argument is strictly greater thankscaleBy(_ k: Int) -> (Int) -> Int: returns a function that multiplies its argument byk
Read three lines:
- An integer
threshold - An integer
scale - A comma-separated list of integers, the
nums
Print three lines:
- The numbers above the threshold (filter with the closure from
greaterThan), joined with, - The same numbers, scaled (map with
scaleBy), joined with, - How many made it through
For input 5 / 3 / 2,7,3,8,9, the output is:
7,8,9
21,24,27
3Cheat sheet
A closure factory is a function that captures a parameter and returns a new closure configured by it:
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
print(triple(4)) // 12Each call produces a brand-new closure with its own captured value of k. The returned closures can be passed directly to map, filter, sorted(by:), etc.:
func greaterThan(_ k: Int) -> (Int) -> Bool {
return { n in n > k }
}
let nums = [2, 7, 3, 8, 9]
let filtered = nums.filter(greaterThan(5)) // [7, 8, 9]
let scaled = filtered.map(multiplier(3)) // [21, 24, 27]Try it yourself
let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// TODO: greaterThan, scaleBy; filter then map; print joined and count
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
Count and IndicesCase and TrimSearching in StringsSplitting and JoiningReplacing SubstringsRecap - Username Check8Closures
Closure BasicsTrailing ClosuresCapturing ValuesReturning ClosuresCustom Higher-OrderRecap - Pipeline Builder