Menu
Coddy logo textTech

Propagation des erreurs

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

Une fonction qui lève une erreur peut appeler d'autres fonctions qui lèvent des erreurs. L'erreur se propage automatiquement jusqu'au do/catch le plus proche, aucune relance manuelle n'est nécessaire.

enum AuthError: Error { case badUser, badPass }

func loadUser(_ name: String) throws -> String {
    if name.isEmpty { throw AuthError.badUser }
    return name
}

func login(_ name: String, _ pass: String) throws -> String {
    let u = try loadUser(name)            // transmet l'erreur
    if pass.count < 4 { throw AuthError.badPass }
    return "hello \(u)"
}

do {
    print(try login("", "abcd"))
} catch AuthError.badUser {
    print("missing user")
} catch AuthError.badPass {
    print("weak password")
}

Lisez de haut en bas : login appelle loadUser avec try. Si loadUser lève une exception, l'erreur ignore le corps de login et arrive au catch extérieur. Vous écrivez chaque étape pour qu'elle échoue rapidement et laissez l'appelant décider de la marche à suivre.

challenge icon

Défi

Moyen

Construisez un petit pipeline de deux étapes pouvant lever des erreurs.

Définissez StepError: Error avec deux cas : negative, tooBig.

Définissez parseSafe(_ s: String) throws -> Int : lève .negative lorsque l'entier analysé est inférieur à 0, sinon le retourne. (Supposez que l'entrée est analysable, vous avez géré cela ailleurs.)

Définissez capStrict(_ n: Int) throws -> Int : lève .tooBig lorsque n > 100, sinon retourne n.

Définissez processStep(_ s: String) throws -> Int qui appelle parseSafe puis capStrict, en laissant toute erreur se propager.

Lisez une seule ligne d'entrée : une liste de chaînes de caractères séparées par des virgules. Pour chacune d'elles, appelez processStep dans un bloc do/catch et affichez une ligne :

  • ok: <n> en cas de succès
  • negative lorsque parseSafe a levé une erreur
  • too big lorsque capStrict a levé une erreur

Pour l'entrée 10,-1,200,42, la sortie est :

ok: 10
negative
too big
ok: 42

Aide-mémoire

Une fonction lançant des erreurs peut appeler d'autres fonctions lançant des erreurs avec try. Les erreurs se propagent automatiquement jusqu'au do/catch le plus proche :

enum AuthError: Error { case badUser, badPass }

func loadUser(_ name: String) throws -> String {
    if name.isEmpty { throw AuthError.badUser }
    return name
}

func login(_ name: String, _ pass: String) throws -> String {
    let u = try loadUser(name)   // l'erreur se propage si elle est lancée
    if pass.count < 4 { throw AuthError.badPass }
    return "hello \(u)"
}

do {
    print(try login("", "abcd"))
} catch AuthError.badUser {
    print("missing user")
} catch AuthError.badPass {
    print("weak password")
}

Si loadUser lance une erreur, l'exécution ignore le reste de login et arrive directement au catch extérieur. Aucune relance manuelle n'est nécessaire.

Essayez vous-même

let parts = readLine()!.components(separatedBy: ",")

// TODO: enum StepError; parseSafe; capStrict; processStep;
// pour chaque partie, faire/essayer processStep, attraper chaque branche, imprimer
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