๐ŸŽ“ A1Learner
๐Ÿ”
0 of 36 lessons completed

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?