Adloun

Trois filtrages, trois diagnostics

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 2 — Le langage OCaml

Énoncé

Le compilateur refuse le premier et signale les deux autres. Que dit-il, et pourquoi a-t-il raison ?


(* a *) let egaux c = match c with
          | (x, x) -> true
          | _ -> false

(* b *) let decrire l = match l with
          | _ -> "quelconque"
          | [] -> "vide"

(* c *) type forme = Cercle of float
                   | Rectangle of float * float
                   | Triangle of float * float
        let aire f = match f with
          | Cercle r -> 3.14159 *. r *. r
          | Rectangle (l, h) -> l *. h

Corrigé


(a) Error: Variable x is bound several times in this matching
(b) Warning 11 [redundant-case]: this match case is unused.
(c) Warning 8 [partial-match]: this pattern-matching is not exhaustive.
      Here is an example of a case that is not matched: Triangle (_, _)

(a) est une erreur, les deux autres des avertissements, et cette différence de statut est instructive.

Un motif lie des noms ; il ne teste pas d'égalité. Écrire (x, x) demanderait de lier x deux fois, ce que l'annexe interdit explicitement : les motifs « ne doivent pas comporter de variable utilisée antérieurement ni deux fois la même variable ». Le langage ne peut pas deviner qu'on voulait dire « les deux composantes sont égales » — cela s'écrit | (a, b) -> a = b. C'est une faute de syntaxe des motifs, donc une erreur.

(b) L'ordre compte « quand [les motifs] ont des instances communes » : _ a pour instances toutes les listes, donc [] en particulier. Le second cas est inatteignable. Le motif le plus général se place toujours en dernier.

(c) Le filtrage oublie Triangle, et le compilateur nomme le cas manquant. À l'exécution, aire (Triangle (3.0, 4.0)) lèverait Match_failure.

En pratique — Un avertissement de filtrage se corrige, il ne s'ignore pas

C'est le service que le chapitre chap:langage-c ne pouvait pas rendre : un switch en C accepte sans un mot qu'on oublie un cas. Ici, ajouter un constructeur à un type fait crier tous les filtrages qui ne l'ont pas prévu — le compilateur vous donne la liste exhaustive des endroits à mettre à jour. On se garde donc d'écrire un | _ -> ... paresseux sur un type somme : il éteint précisément l'alarme qu'on voulait garder.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.