closure

Bonjour,

Dans la formation de Paul Hudson, au début du chapitre sur les "closures", il y a un petit bout de code que je comprends pas du tout:

let team = ["Gloria", "Suzanne", "Piper", "Tiffany", "Tasha"]

let captainFirstTeam = team.sorted(by: { (name1: String, name2: String) -> Bool in
    if name1 == "Suzanne" {
        return true
    } else if name2 == "Suzanne" {
        return false
    }

    return name1 < name2
})

print(captainFirstTeam)

Ce code trie le tableau "team" par ordre alphabétique en mettant "Suzanne" au début.
Je ne comprends pas ce que sont les paramètres name1 et name2, je ne comprends pas pourquoi il y en a deux et je ne comprends pas ce que font les booléens.
Et pour finir je ne comprends pas la ligne "return name1 < name2". On retourne un booléen mais à quoi sert-il?

Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur
    octobre 2022 modifié #2

    Le prototype de la fonction sorted est:

    func sorted(by areInIncreasingOrder: (Self.Element, Self.Element) throws -> Bool) rethrows -> [Self.Element]
    

    La paramètre areInIncreasingOrder est une closure qui prend un tuple de deux éléments, et renvoie true si le premier élément doit être classé avant le second.

    Question syntaxe, la closure passée va avoir cette forme:

    { (élement1, élement2) in
        // renvoyer un Bool
    }
    

    À présent, considérons cet exemple plus simple:

    let captainFirstTeam = team.sorted(by: { (name1: String, name2: String) -> Bool in
        return name1 < name2
    })
    

    Ça veut dire que le tableau team va être parcouru et que la closure va être appelée pour déterminer lequel de name1 ou name2 doit apparaître en premier.

    Ce qui peut être perturbant est name1 < name2. Autant quand on compare des nombres réels, on comprend bien ce que signifie <, autant pour des chaînes, c'est plus abstrait. Mais ça se conçoit quand même: la chaîne est considérée inférieure si elle apparaît avant dans un classement alphabétique.

    Pour l'exemple final

    let captainFirstTeam = team.sorted(by: { (name1: String, name2: String) -> Bool in
        if name1 == "Suzanne" {
            return true
        } else if name2 == "Suzanne" {
            return false
        }
    
        return name1 < name2
    })
    

    Il y a juste une exception au classement pour que "Suzanne" soit toujours considérée comme la plus petite chaîne.

  • Alors, dans cette closure sort(by:) qui est basique voici ce qu'il se passe :

    Peu importe l'algortihme de tri qui est utilisé derrière par Apple (tri par bulle, tri cocktail, etc.), la closure te demande juste ceci :
    Prenons name1 et name2 deux éléments qui peuvent être n'importe éléments de teams, quelle serait la logique pour les trier/comparer, ie lequel placer avant l'autre: tu dois retourner true s'il faut placer name1 avant name2 et false s'il faut placer name2 avant name1.
    Donc, il y a le premier test if/else pour placer Suzanne spécifiquement devant.
    Et le dernier name1 < name2, c'est parce que String est comparable, donc tu peux "évaluer" "abc" < "bcd", et "abc" est inférieur à "bcd" (ordre alphabétique).

    Tu peux modifier la closure ainsi :

    let captainFirstTeam = team.sorted(by: { (name1: String, name2: String) -> Bool in
        print("Evaluating: \(name1) vs \(name2)")
    
        if name1 == "Suzanne" {
            print("name1 is Suzanne -> return true")
            return true
        } else if name2 == "Suzanne" {
            print("name2 is Suzanne -> return true")
            return false
        }
    
    
        let test = name1 < name2
        print("Comparing name1 < name2: \(test)")
        return test
    })
    

    Ensuite, tu peux modifier, rajouter des éléments de team et ainsi voir les print.

  • @Céroce et @Larme, merci à tous les deux.
    Pour une mystérieuse raison, je n'ai pas pensé que le code de la fonction sorte() fut visible :D
    Dès lors, j'avais l'impression que name1 et name2 sortait d'un chapeau...

Connectez-vous ou Inscrivez-vous pour répondre.