Swift Autoclosures
An autoclosure wraps an argument expression in a closure automatically. The wrapped work runs only when the function chooses to call that closure.
A plain value as an autoclosure
The caller passes a plain string with no braces. The function calls the wrapped closure and prints the text.
func show(_ value: @autoclosure () -> String) {
print(value())
}
show("plain text")
show("second line")Delayed evaluation
The counter rises inside nextValue each time that function runs. The prints prove the expression runs once, at the moment the function reads it.
var evaluations = 0
func nextValue() -> Int {
evaluations += 1
return 42
}
func read(_ value: @autoclosure () -> Int) {
print("before the read")
print(value())
print(evaluations)
}
read(nextValue())
print(evaluations)A check that can be skipped
The decide function reads its fallback only when the ready flag is false. The first call never runs the expensive check, so the counter stays at zero.
var checks = 0
func expensiveCheck() -> Bool {
checks += 1
return true
}
func decide(_ ready: Bool, fallback: @autoclosure () -> Bool) {
if ready {
print("ready")
} else if fallback() {
print("fallback passed")
} else {
print("failed")
}
}
decide(true, fallback: expensiveCheck())
print(checks)
decide(false, fallback: expensiveCheck())
print(checks)Example
var builds = 0
func buildMessage() -> String {
builds += 1
return "report ready"
}
func log(_ enabled: Bool, _ message: @autoclosure () -> String) {
if enabled {
print(message())
}
}
log(false, buildMessage())
print(builds)
log(true, buildMessage())
print(builds)Key points
- The @autoclosure mark goes on a closure parameter in a function.
- The caller writes a plain expression and passes no braces.
- The expression stays untouched until the function calls the closure.
- A function can skip the call and leave the expression unevaluated.
- Each call of the closure runs the expression one more time.
In this example, the log function reads its message only when the enabled flag is true. The first call skips the read, so the build counter stays at zero. The second call reads the message, prints report ready, and lifts the counter to one.
Note
autoclosures suit checks that a function may never need to run.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
When does an autoclosure argument expression run?