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 *. hCorrigé
(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.