152 votes

Comment utiliser Swift @autoclosure

J'ai remarqué en écrivant un assert dans Swift que la première valeur est typée en tant que

@autoclosure() -> Bool

avec une méthode surchargée pour renvoyer une méthode générique T pour en tester l'existence via la valeur LogicValue protocol .

Cependant, si l'on s'en tient strictement à la question qui nous occupe. Il semble vouloir un @autoclosure qui renvoie un Bool .

L'écriture d'une fermeture réelle qui ne prend pas de paramètres et renvoie un Bool ne fonctionne pas, elle veut que j'appelle la fermeture pour la faire compiler, comme ceci :

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

Cependant, le simple fait de passer un Bool fonctionne :

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

Alors, qu'est-ce qui se passe ? Qu'est-ce que @autoclosure ?

Editar: @auto_closure a été renommé @autoclosure

0voto

yoAlex5 Points 2350

@autoclosure

@autoclosure convertit(wraps) l'expression à l'intérieur du paramètre de la fonction dans une closure [À propos]

Pour :

  • facile à lire assert(2 == 5, "failed")
  • les accolades ne sont pas utilisées

Cons

  • difficile à lire. Lorsque vous passez une fonction dans @autoclosure il n'est pas clair que cette fonction sera reportée (car il s'agit d'une fermeture à l'intérieur). fooWithAutoClosure(a: foo0()) - foo0() ne sera pas appelé immédiatement comme on s'y attend en lisant cette ligne

Une utilisation excessive des autoclaves peut rendre votre code difficile à comprendre. Le contexte et le nom de la fonction doivent indiquer clairement que l'évaluation est différée.

Document officiel

  • @autoclosure ne prend pas de paramètres

    func foo(p: @autoclosure () -> Void)
  • @autoclosure accepter toute fonction avec seulement des a retourné type

Autres exemples

//functions block
func foo0() -> String {
    return "foo0"
}

func foo1(i1: Int) -> String {
    return "foo1 " + String(i1)
}

func foo2(i1: Int, i2: Int) -> String {
    return "foo2 " + String(i1 + i2)
}

//closures block
func fooWithClosure0(p: () -> String) -> String {
    return "fooWithClosure0 " + p()
}

func fooWithClosure1(p: (Int) -> String) -> String {
    return "fooWithClosure1 " + p(1)
}

func fooWithClosure2(p: (Int, Int) -> String) -> String {
    return "fooWithClosure2 " + p(1, 2)
}

//@autoclosure
func fooWithAutoClosure(a: @autoclosure () -> String) -> String {
    return "fooWithAutoClosure " + a()
}

//test closures
func testClosures() {
    XCTAssertEqual("fooWithClosure0 foo0", fooWithClosure0(p: foo0))
    XCTAssertEqual("fooWithClosure1 foo1 1", fooWithClosure1(p: foo1))
    XCTAssertEqual("fooWithClosure2 foo2 3", fooWithClosure2(p: foo2))

    XCTAssertEqual("fooWithClosure2 foo2 3", fooWithClosure2(p: { (i1, i2) -> String in
        return "fooWithClosure2 " + "foo2 " + String(i1 + i2)
    }))
}

//test @autoclosure
func testAutoClosures() {
    XCTAssertEqual("fooWithAutoClosure HelloWorld", fooWithAutoClosure(a: "HelloWorld")) //"HelloWorld" is String as returned value of @autoclosure

    XCTAssertEqual("fooWithAutoClosure foo0", fooWithAutoClosure(a: foo0()))
    XCTAssertEqual("fooWithAutoClosure foo1 1", fooWithAutoClosure(a: foo1(i1: 1)))
    XCTAssertEqual("fooWithAutoClosure foo2 3", fooWithAutoClosure(a: foo2(i1: 1, i2: 2)))
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X