Как использовать Swift @autoclosure



я заметил, когда пишу assert в SWIFT, что первое значение вводится как



@autoclosure() -> Bool


С перегруженным методом для возврата общего T значением, чтобы проверить существование через LogicValueprotocol.



однако строго придерживаясь вопроса под рукой. Кажется, он хочет @autoclosure что возвращает Bool.



написание фактического закрытия, которое не принимает никаких параметров и возвращает Bool, не работает, он хочет, чтобы я вызвал закрытие, чтобы сделать он компилируется, вот так:



assert({() -> Bool in return false}(), "No user has been set", file: __FILE__, line: __LINE__)


однако просто передача Bool работает:



assert(false, "No user has been set", file: __FILE__, line: __LINE__)


так что же происходит? Что такое @autoclosure?



Edit:@auto_closure была переименована в @autoclosure

726   5  

5 ответов:

рассмотрим функцию, которая принимает один аргумент, простое замыкание, которое не принимает аргумент:

func f(pred: () -> Bool) {
    if pred() {
        print("It's true")
    }
}

чтобы вызвать эту функцию, мы должны пройти в закрытие

f(pred: {2 > 1})
// "It's true"

если мы опускаем фигурные скобки, мы передаем выражение, и это ошибка:

f(pred: 2 > 1)
// error: '>' produces 'Bool', not the expected contextual result type '() -> Bool'

@autoclosure создает автоматическое закрытие вокруг выражения. Поэтому, когда вызывающий пишет выражение типа 2 > 1, он автоматически завернут в закрытие, чтобы стать {2 > 1} перед перешел к f. Так что если мы применим это к функции f:

func f(pred: @autoclosure () -> Bool) {
    if pred() {
        print("It's true")
    }
}

f(pred: 2 > 1)
// It's true

так что он работает только с выражением без необходимости обернуть его в закрытие.

вот практический пример - мой print override (это Swift 3):

func print(_ item: @autoclosure () -> Any, separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    Swift.print(item(), separator:separator, terminator: terminator)
    #endif
}

когда вы говорите print(myExpensiveFunction()) мой print override затмевает Swift print и называется. myExpensiveFunction() таким образом, завернутый в закрытие и не оценены. Если мы находимся в режиме выпуска, это будет никогда быть оценены, потому что item() не назовешь. Таким образом, у нас есть версия print это не оценивает его аргументы в режиме выпуска.

описание auto_closure из документов:

вы можете применить атрибут auto_closure к типу функции, который имеет параметр type of () и который возвращает тип выражения (см. атрибут type.) Функция автоклавирования фиксирует неявное закрытие над указанным выражением, вместо самого выражения. Этот в следующем примере используется атрибут auto_closure при определении очень простая функция утверждать:

и вот пример, который apple использует вместе с ним.

func simpleAssert(condition: @auto_closure () -> Bool, message: String) {
    if !condition() {
        println(message)
    }
}
let testNumber = 5
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")

в основном это означает, что вы передаете логическое выражение в качестве первого аргумента вместо закрытия, и оно автоматически создает закрытие из него для вас. Вот почему вы можете передать false в метод, потому что это логическое выражение, но не могу пройти закрытие.

Это показывает полезный случай @autoclosure https://airspeedvelocity.net/2014/06/28/extending-the-swift-language-is-cool-but-be-careful/

теперь условное выражение, переданное в качестве первого параметра в until, будет автоматически обернуто в выражение закрытия и может вызываться каждый раз вокруг цикла

func until<L: LogicValue>(pred: @auto_closure ()->L, block: ()->()) {
    while !pred() {
        block()
    }
}

// doSomething until condition becomes true
until(condition) {
    doSomething()
}

Это просто способ избавиться от фигурных скобок в вызове закрытие, простой пример:

    let nonAutoClosure = { (arg1: () -> Bool) -> Void in }
    let non = nonAutoClosure( { 2 > 1} )

    let autoClosure = { (arg1: @autoclosure () -> Bool) -> Void in }
    var auto = autoClosure( 2 > 1 ) // notice curly braces omitted

Comments

    Ничего не найдено.