Reputation: 2154
Since Apple states An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure., why autoclosure delay evaluation and normal course does not?
I borrow the snippet with autoclosure from John Sundell to compare with/without autoclosure.
func assert2(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {
guard isDebug else {
return
}
// Inside assert we can refer to expression as a normal closure
if !expression() {
assertionFailure(message())
}
}
func assert3(_ expression: () -> Bool,
_ message: () -> String) {
guard isDebug else {
return
}
// Inside assert we can refer to expression as a normal closure
if !expression() {
assertionFailure(message())
}
}
But it seems the message()
will not be executed in both cases.
The only difference for me is I need to make closure manually:
override func viewDidLoad() {
super.viewDidLoad()
assert2(false, "hello2")
assert3({return false}, {return "hello3"})
}
Is there some other reason that Apple and John Sundell say the autoclosure delay the execution? For example, are normal closure being pre-evaluated because of optimization from Xcode? Or any other reasons that closures behave in this way?
Please provide an official document if there's any which explaining this point explicitly.
Upvotes: 0
Views: 112
Reputation: 274480
I think you misunderstood the distinction that the documentation is trying to draw. When the documentation says:
An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure.
It's not comparing @autoclosure () -> Bool
(an "autoclosure") against () -> Bool
(a "normal closure"). It's comparing @autoclosure () -> Bool
to Bool
.
The documentation is assuming that the caller stays the same, specifically in the case that the caller passes some expressions to the method. For example, for such a calling code:
assert(someBoolFunction(), someStringFunction())
Using @autoclosure
will allow someBookFunction
to be run at a later time (or not at all), whereas accepting a Bool
will cause someBoolFunction
to be called immediately, even before assert
is called. This is because @autoclosure
indicates that whatever expression is passed is wrapped into a closure via the magics of syntactic sugar.
Note that changing a function's parameter from Bool
to @autoclosure () -> Bool
is generally not a breaking change to the caller (the caller will still be able to pass expressions to the function), which is why this is a meaningful comparison.
Upvotes: 1