What is the difference and purpose of auto and esc

2019-04-02 02:44发布

问题:

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.