Le point-virgule qui sort du then
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 2 — Le langage OCaml
Énoncé
Cette fonction doit rendre le nombre de termes strictement positifs et leur somme. Sur [| 3; -1; 4; -1; 5 |] elle rend (3, 10) au lieu de (3, 12). Pourquoi, et comment corriger ?
let somme_des_positifs t =
let positifs = ref 0 and total = ref 0 in
for i = 0 to Array.length t - 1 do
if t.(i) > 0 then
incr positifs;
total := !total + t.(i)
done;
(!positifs, !total)Corrigé
L'indentation ment. Elle suggère que les deux lignes sont dans le then ; le langage en décide autrement. L'annexe prévient : « les retours à la ligne et l'indentation ne sont pas signifiants ». Le point-virgule sépare deux expressions, et il lie moins fort que le if : le corps de la boucle se lit
(if t.(i) > 0 then incr positifs) ; (total := !total + t.(i))
La somme est donc calculée sur tous les termes : . Le compte, lui, est juste — d'où un résultat à moitié correct, le plus difficile à repérer.
La correction, mesurée :
let somme_des_positifs t =
let positifs = ref 0 and total = ref 0 in
for i = 0 to Array.length t - 1 do
if t.(i) > 0 then begin
incr positifs;
total := !total + t.(i)
end
done;
(!positifs, !total)
(* [| 3; -1; 4; -1; 5 |] donne maintenant (3, 12) = (3, 3 + 4 + 5) *)
begin ... end — ou une paire de parenthèses, strictement équivalente — groupe les deux expressions en une seule, qui devient le then.
Pourquoi le compilateur ne dit rien. Parce que le programme est bien typé : incr positifs a le type unit, et un if sans else de type unit est licite. C'est un des rares endroits où le typage fort ne rattrape rien : il vérifie les types, pas les intentions. La parade est une habitude, pas un outil — on met begin ... end dès que le corps d'un then compte plus d'une expression, même quand ce n'est pas nécessaire.
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.