Menu
Coddy logo textTech

Retourner des closures

Fait partie de la section Logique et Flux du Journey Swift de Coddy — leçon 41 sur 56.

Vous avez vu makeCounter retourner une closure. La même astuce vous permet de construire un comportement configurable : prenez des paramètres une fois, et obtenez en retour une fonction qui les utilise plusieurs fois.

func multiplier(_ k: Int) -> (Int) -> Int {
    return { n in n * k }
}

let triple = multiplier(3)
let tenfold = multiplier(10)
print(triple(4))                  // 12
print(tenfold(4))                 // 40

La closure retournée capture k, donc chaque appel à multiplier(...) produit une toute nouvelle closure avec son propre k.

Ce patron est au cœur du code de « stratégie » en Swift : écrivez une fonction qui prend une configuration et renvoie une closure, puis passez la closure à map, filter, sorted(by:), ou partout ailleurs où une valeur de type fonction est attendue.

challenge icon

Défi

Moyen

Construisez deux fabriques de fermetures (closure factories) :

  • greaterThan(_ k: Int) -> (Int) -> Bool : renvoie un prédicat qui est true lorsque son argument est strictement supérieur à k
  • scaleBy(_ k: Int) -> (Int) -> Int : renvoie une fonction qui multiplie son argument par k

Lisez trois lignes :

  1. Un entier threshold
  2. Un entier scale
  3. Une liste d'entiers séparés par des virgules, les nums

Affichez trois lignes :

  1. Les nombres supérieurs au seuil (filtrez avec la fermeture de greaterThan), joints par ,
  2. Ces mêmes nombres, mis à l'échelle (mappez avec scaleBy), joints par ,
  3. Le nombre d'éléments qui ont été conservés

Pour l'entrée 5 / 3 / 2,7,3,8,9, la sortie est :

7,8,9
21,24,27
3

Aide-mémoire

Une fabrique de fermetures est une fonction qui capture un paramètre et renvoie une nouvelle fermeture configurée par celui-ci :

func multiplier(_ k: Int) -> (Int) -> Int {
    return { n in n * k }
}

let triple = multiplier(3)
print(triple(4))   // 12

Chaque appel produit une toute nouvelle fermeture avec sa propre valeur capturée de k. Les fermetures renvoyées peuvent être passées directement à map, filter, sorted(by:), etc. :

func greaterThan(_ k: Int) -> (Int) -> Bool {
    return { n in n > k }
}

let nums = [2, 7, 3, 8, 9]
let filtered = nums.filter(greaterThan(5))  // [7, 8, 9]
let scaled = filtered.map(multiplier(3))    // [21, 24, 27]

Essayez vous-même

let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }

// TODO: greaterThan, scaleBy; filtrer puis mapper; afficher les éléments joints et le compte
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Logique et Flux