I am looking for some of the difference/purpose of autoclosure and escaping closure in Swift. I know well that an escaping closure is something we want to execute after the function has been returned but I didn't get the concept of an autoclosure.
问题:
回答1:
I didn't get the concept of autoclosure closure.
The autoclosure allows a function to wrap an expression in a closure so that it can be executed later or not at all.
A good example of the use of an autoclosure is the short-circuit behavior that happens with ||
.
Consider this example:
func willCrash() -> Bool {
fatalError()
return true
}
let good = true
if good || willCrash() {
print("made it")
}
Output:
made it
The ||
operator uses short-circuit evaluation: The left-hand side (lhs) is evaluated first, and the right-hand side (rhs) is evaluated only if lhs evaluates to false.
So, how is that implemented? Well, ||
is simply a function that takes two arguments that each evaluate to a Bool
and ||
combines them to return a Bool
. But in the normal calling scheme of a function in Swift, the arguments are evaluated before the function is called. If ||
was implemented in the obvious way:
func ||(lhs: Bool, rhs: Bool) -> Bool {
return lhs ? true : rhs
}
it would crash because of the execution of willCrash()
before ||
was called. So ||
employs autoclosure to wrap the second statement in a closure so that it can delay evaluation until it is inside the ||
function. If the first statement (which is evaluated before ||
was called) is true
then the result of the ||
is true
and the closure is not called thus avoiding the crash in this example.
Here is the definition of ||
:
static func ||(lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool
Description Performs a logical OR operation on two Bool values. The logical OR operator (||) combines two Bool values and returns true if at least one of the values is true. If both values are false, the operator returns false.
This operator uses short-circuit evaluation: The left-hand side (lhs) is evaluated first, and the right-hand side (rhs) is evaluated only if lhs evaluates to false.
Ignoring the throws/rethrows which is another topic, the implementation of ||
becomes:
func ||(lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
return lhs ? true : rhs()
}
and rhs()
is only called when lhs == false
.
回答2:
The documentation is all thoroughly described (with examples), but if you have any other questions, please ask me
Escaping Closures
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.
Autoclosures
An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.