method functions examples closure closures swift

closures - functions - Cómo usar Swift @autoclosure



swift functions (5)

Aquí hay un ejemplo práctico: mi anulación de print (esta es Swift 3):

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

Cuando dices print(myExpensiveFunction()) , mi anulación de print eclipsa la print de Swift y se print(myExpensiveFunction()) . myExpensiveFunction() se envuelve en un cierre y no se evalúa . Si estamos en modo Liberación, nunca será evaluado, porque no se llamará al item() . Por lo tanto, tenemos una versión de print que no evalúa sus argumentos en el modo de lanzamiento.

Me di cuenta al escribir una assert en Swift que el primer valor se escribe como

@autoclosure() -> Bool

con un método sobrecargado para devolver un valor T genérico, para probar la existencia a través del protocol LogicValue .

Sin embargo, se atiene estrictamente a la pregunta que nos ocupa. Parece querer un @autoclosure que devuelva un Bool .

Escribir un cierre real que no tome parámetros y devuelva un Bool no funciona, quiere que llame al cierre para hacer que se compile, así:

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

Sin embargo, simplemente pasar un Bool funciona:

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

¿Entonces qué está pasando? ¿Qué es @autoclosure ?

Editar: @auto_closure se renombró @autoclosure


Considere una función que toma un argumento, un cierre simple que no tiene argumento:

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

Para llamar a esta función, tenemos que pasar un cierre

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

Si omitimos las llaves, estamos pasando una expresión y eso es un error:

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

@autoclosure crea un cierre automático alrededor de la expresión. Entonces, cuando la persona que llama escribe una expresión como 2 > 1 , se ajusta automáticamente a un cierre para convertirse en {2 > 1} antes de pasarla a f . Entonces, si aplicamos esto a la función f :

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

Por lo tanto, funciona con solo una expresión sin la necesidad de envolverlo en un cierre.


Descripción de auto_closure de los documentos:

Puede aplicar el atributo auto_closure a un tipo de función que tenga un tipo de parámetro de () y que devuelva el tipo de una expresión (consulte Atributos de tipo). Una función de cierre automático captura un cierre implícito sobre la expresión especificada, en lugar de la expresión misma. El siguiente ejemplo usa el atributo auto_closure para definir una función de afirmación muy simple:

Y aquí está el ejemplo que la manzana usa junto con él.

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.")

Básicamente, lo que significa es pasar una expresión booleana como primer argumento en lugar de un cierre y automáticamente crea un cierre para usted. Es por eso que puede pasar falso en el método porque es una expresión booleana, pero no puede pasar un cierre.


Es solo una manera de deshacerse de las llaves en una llamada de cierre, ejemplo simple:

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


Esto muestra un caso útil de @autoclosure https://airspeedvelocity.net/2014/06/28/extending-the-swift-language-is-cool-but-be-careful/

Ahora, la expresión condicional pasada como el primer parámetro a hasta se envolverá automáticamente en una expresión de cierre y se podrá invocar cada vez que se repita el ciclo

func until<L: LogicValue>(pred: @auto_closure ()->L, block: ()->()) { while !pred() { block() } } // doSomething until condition becomes true until(condition) { doSomething() }