Fermetures rapides


Les fermetures sont des blocs autonomes de code fonctionnel qui peuvent être utilisés dans le code ou utilisés pour transmettre des valeurs en tant que paramètres.

Les fermetures dans Swift sont similaires aux blocs en C et Objective-C, ainsi qu'aux fonctions anonymes dans certains autres langages de programmation.

Les fonctions globales et les fonctions imbriquées sont en fait des fermetures spéciales.

La forme de clôture est :

全局函数嵌套函数闭包表达式
有名字但不能捕获任何值。有名字,也能捕获封闭函数内的值。无名闭包,使用轻量级语法,可以根据上下文环境捕获值。

Il existe de nombreuses optimisations pour les fermetures dans Swift :

  1. Déduction des types de paramètres et de valeurs de retour en fonction du contexte

  2. À partir d'une seule ligne expression Retour implicite dans la fermeture (c'est-à-dire que le corps de la fermeture n'a qu'une seule ligne de code, le retour peut être omis)

  3. Vous pouvez utiliser des noms de paramètres simplifiés, tels que $0, $1 ( à partir de 0, indiquant le i-ème paramètres...)

  4. fournit une syntaxe de fermeture de fin (Trailing Closure syntax)

  5. syntaxe

    Ce qui suit définit des paramètres de réception et renvoie la syntaxe de fermeture du type spécifié :

    {(parameters) -> return type in
       statements
    }

    Instance

    import Cocoa
    
    let studname = { print("Swift 闭包实例。") }
    studname()

    Le résultat de sortie de l'exécution du programme ci-dessus est :

    Swift 闭包实例。

    Le formulaire de fermeture suivant reçoit deux paramètres et renvoie une valeur booléenne :

    {(Int, Int) -> Bool in
       Statement1
       Statement 2
        ---
       Statement n
    }

    Instance

    import Cocoa
    
    let divide = {(val1: Int, val2: Int) -> Int in 
       return val1 / val2 
    }
    let result = divide(200, 20)
    print (result)

    Le résultat de sortie de l'exécution du programme ci-dessus est :

    10

    Expression de clôture

    L'expression de fermeture est un moyen de construire des fermetures en ligne en utilisant une syntaxe concise. Les expressions de fermeture fournissent des optimisations de syntaxe qui rendent l'écriture de fermetures simple et directe.


    fonction de tri

    La bibliothèque standard Swift fournit une fonction appelée sort, qui trie les valeurs dans un tableau de types connus en fonction de la fonction de fermeture que vous fournissez pour le tri.

    Une fois le tri terminé, la méthode sort(_:) renverra un nouveau tableau de la même taille que le tableau d'origine, contenant des éléments du même type et les éléments auront été correctement triés. ne pas être modifié par la méthode sort(_:). La méthode

    sort(_:) doit transmettre deux paramètres :

    • Un tableau de types connus

    • Closure Fonction, cette fonction de fermeture doit transmettre deux valeurs du même type que les éléments du tableau, et renvoie une valeur booléenne pour indiquer si le premier paramètre transmis est classé avant ou après le deuxième paramètre lorsque le tri est terminé . Si la première valeur du paramètre apparaît avant la deuxième valeur du paramètre, la fonction de fermeture de tri doit renvoyer true, sinon elle renvoie false.

    Instance

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    // 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
    func backwards(s1: String, s2: String) -> Bool {
        return s1 > s2
    }
    var reversed = names.sort(backwards)
    
    print(reversed)

    Le résultat de l'exécution du programme ci-dessus est :

    ["S", "D", "BE", "AT", "AE"]

    Si la première chaîne (s1) est supérieure à la deuxième chaîne ( s2 ), la fonction reverse renvoie true, indiquant que s1 doit apparaître avant s2 dans le nouveau tableau. Pour les caractères d'une chaîne, « supérieur à » signifie « se produisant plus tard par ordre alphabétique ». Cela signifie que la lettre « B » est supérieure à la lettre « A » et que la chaîne « S » est supérieure à la chaîne « D ». Il sera trié par ordre alphabétique inverse, "AT" sera trié avant "AE".


    Abréviation du nom du paramètre

    Swift fournit automatiquement une fonction d'abréviation du nom du paramètre pour les fonctions en ligne. Vous pouvez appeler directement les paramètres de fermeture séquentiellement via $0, $1, $2.

    Instance

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort( { 
    ["S", "D", "BE", "AT", "AE"]
     >  } ) print(reversed)

    $0 et $1 représentent les premier et deuxième paramètres de type String dans la fermeture.

    Le résultat de l'exécution du programme ci-dessus est :

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort(>)
    print(reversed)

    Si vous utilisez l'abréviation du nom du paramètre dans l'expression de fermeture, vous pouvez omettre sa définition dans la liste des paramètres de fermeture et faire correspondre le nom du paramètre L'abréviation le type est déduit du type de fonction. Le mot-clé in peut également être omis.


    Fonction opérateur

    Il existe en fait une manière plus courte d'écrire l'expression de fermeture dans l'exemple ci-dessus.

    Le type String de Swift définit une implémentation de chaîne du signe supérieur à (>), qui en tant que fonction accepte deux paramètres de type String et renvoie une valeur de type Bool. Et cela est cohérent avec le type de fonction requis par le deuxième paramètre de la méthode sort(_:). Par conséquent, vous pouvez simplement passer un signe supérieur à et Swift peut automatiquement déduire que vous souhaitez utiliser l'implémentation de la fonction de chaîne du signe supérieur à :

    ["S", "D", "BE", "AT", "AE"]

    Le résultat de l'exécution du programme ci-dessus est :

    func someFunctionThatTakesAClosure(closure: () -> Void) {
        // 函数体部分
    }
    
    // 以下是不使用尾随闭包进行函数调用
    someFunctionThatTakesAClosure({
        // 闭包主体部分
    })
    
    // 以下是使用尾随闭包进行函数调用
    someFunctionThatTakesAClosure() {
      // 闭包主体部分
    }

    Fermeture finale

    La fermeture finale est une expression de fermeture écrite après les parenthèses de la fonction, et la fonction prend en charge son appel comme dernier paramètre. { $0 > $1} après

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    //尾随闭包
    var reversed = names.sort() { 
    ["S", "D", "BE", "AT", "AE"]
     >  } print(reversed)

    instance

    reversed = names.sort { 
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
     >  }

    sort() est une fermeture finale.

    Le résultat de l'exécution du programme ci-dessus est :

    import Cocoa
    
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
    
    let incrementByTen = makeIncrementor(forIncrement: 10)
    
    // 返回的值为10
    print(incrementByTen())
    
    // 返回的值为20
    print(incrementByTen())
    
    // 返回的值为30
    print(incrementByTen())

    Remarque : Si la fonction ne nécessite qu'un seul paramètre, l'expression de fermeture, vous pouvez même omettre le () lorsque vous utilisez une fermeture finale.

    10
    20
    30

    Capturer une valeur

    Une fermeture peut capturer une constante ou une variable dans le contexte dans lequel elle est définie.

    Même si le domaine d'origine dans lequel ces constantes et variables sont définies n'existe plus, la fermeture peut toujours référencer et modifier ces valeurs​​dans le corps de la fonction de fermeture.

    La forme de fermeture la plus simple dans Swift est une fonction imbriquée, qui est une fonction définie dans le corps de fonction d'autres fonctions.

    Les fonctions imbriquées peuvent capturer tous les paramètres de leurs fonctions externes ainsi que les constantes et variables définies.

    Regardez cet exemple :

    import Cocoa
    
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
    
    let incrementByTen = makeIncrementor(forIncrement: 10)
    
    // 返回的值为10
    incrementByTen()
    
    // 返回的值为20
    incrementByTen()
    
    // 返回的值为30
    incrementByTen()
    
    // 返回的值为40
    incrementByTen()
    
    let alsoIncrementByTen = incrementByTen
    
    // 返回的值也为50
    print(alsoIncrementByTen())

    Une fonction makeIncrementor, elle a un paramètre de type Int amout, et elle a un nom de paramètre externe forIncremet, ce qui signifie que lorsque vous appelez, vous devez utiliser ceci nom externe. La valeur de retour est fonction de ()-> Int.

    Dans le titre de la fonction, la variable runningTotal et un incrémenteur de fonction sont déclarés.

    La fonction incrémenteur n'obtient aucun paramètre, mais les variables runningTotal et montant sont accessibles dans le corps de la fonction. En effet, il le fait en capturant les variables runningTotal et montant qui existent déjà dans le corps de la fonction qui le contient.

    Étant donné que la variable de montant n'est pas modifiée, l'incrémenteur capture et stocke en fait une copie de la variable, et la copie est stockée avec l'incrémenteur.

    Ainsi, lorsque nous appellerons cette fonction, elle accumulera :

    50

    Le résultat de sortie de l'exécution du programme ci-dessus est :

    rrreee

    La fermeture est un type de référence

    Dans l'exemple ci-dessus, incrémentByTen est une constante, mais la fermeture pointée par ces constantes peut toujours incrémenter la valeur de la variable qu'elle capture.

    C'est parce que les fonctions et les fermetures sont toutes deux des types de référence.

    Que vous attribuiez une fonction/fermeture à une constante ou à une variable, vous définissez en fait la valeur de la constante/variable sur une référence à la fonction/fermeture correspondante. Dans l'exemple ci-dessus, la référence pointée par incrémentByTen vers la fermeture est une constante, et non le contenu de la fermeture elle-même.

    Cela signifie également que si vous attribuez une fermeture à deux constantes/variables différentes, les deux valeurs pointeront vers la même fermeture :

    rrreee

    Le résultat de l'exécution du programme ci-dessus est :

    rrreee