Le but est d'être capable de déchiffrer les messages d'erreurs du compilateur, car vous ferez forcément un jour ou l'autre des petites erreurs dans votre code. Bien lire les parties sur les messages d'erreur permet ensuite de gagner beaucoup de temps lorsque vous programmez.
Simulons d'abord l'oubli d'un point-virgule :
print_int 5 print_newline();
On obtient le message suivant (en supposant que le fichier source est test.ml
) :
File "test.ml", line 1, characters 0-9: This function is applied to too many arguments, maybe you forgot a `;'
D'abord on remarque que le compilateur est subtil sur un cas aussi simple, puisqu'il suggère l'oubli possible d'un point-virgule : "maybe you forgot a `;'"
. Mais ce ne sera pas toujours le cas, et souvent il faudra se contenter de la phrase précédente : "This function is applied to too many arguments"
, traduction : "Cette fonction est appliquée avec trop d'arguments"
. De quelle fonction parle le compilateur ? C'est indiqué juste au-dessus : il s'agit de la fonction dont le nom est compris entre les caractères 0 et 9 de la ligne numéro 1. En regardant le code, on s'aperçoit que c'est "print_int"
. "print_int"
s'utilise normalement en écrivant simplement un entier derrière. Ici, on a écrit d'autre choses après le 5 dans l'expression : print_int 5 print_newline()
. D'où le message disant que trop d'arguments ont été fournis.
Testons maintenant un autre oubli, celui de parenthèses après print_newline()
.
print_string "Voici dix-huit : "; print_newline; print_int 18;
On obtient le message suivant :
File "test.ml", line 2, characters 0-13: Warning: this function application is partial, maybe some arguments are missing.
Un avertissement nous est donné : la fonction print_newline
est appliquée "partiellement"
. Lorsqu'on étudiera les fonctions, on comprendra la signification exacte du "partiellement"
, et on verra pourquoi les parenthèses ()
sont appelées "arguments"
. Pour l'instant, retenons simplement qu'il s'agit d'un oubli de quelque chose à la suite du nom de la fonction, ici print_newline
.
Comme il ne s'agit que d'un avertissement, le programme fonctionne tout de même. Seulement il ne fait pas ce qu'on l'on souhaitait, puisque aucun retour à la ligne n'est effectué :
Voici dix-huit : 18
Étudions encore un petit problème courant avec les nombres négatifs :
print_int -16;
Donne :
File "test.ml", line 1, characters 0-9: This expression has type int -> unit but is here used with type int
On expliquera dans le chapitre suivant que ce message veut dire que le compilateur essaie d'effectuer la soustraction entre print_int
et 16
, et qu'il n'y arrive pas car print_int
n'est pas un entier. Ce qu'il faut retenir, c'est que la version correcte utilise des parenthèses :
print_int (-16);
Pour la même raison, il faudra ajouter des parenthèses autour des nombres négatifs pour effectuer des calculs :
print_int (-267); print_string " a pour carré "; print_int ((-267) * (-267));
Considérons le programme suivant, qui affiche 5, puis le texte "a pour carré"
, et enfin le carré de 5. Notez qu'on ne va pas afficher 25 cette fois, mais bien le résultat du calcul de 5 fois 5. Pour utiliser print_int
correctement, il faut le faire suivre d'un entier, et rien d'autre. Si on veut afficher le résultat de 5 * 5
, il est impératif de le mettre entre parenthèses. Comme en mathématiques, les parenthèses les plus imbriquées sont calculées en premier.
print_int 5; print_string " a pour carré "; print_int (5 * 5);
On aimerait maintenant faire la même chose pour 238, afin d'afficher la phrase indiquant sa valeur et celle de son carré. Il suffit pour cela de remplacer 5 par 238.
print_int 238; print_string " a pour carré "; print_int (238 * 238);
Si on voulait recommencer avec d'autres valeurs, on serait obligé de faire 3 remplacements à chaque fois, ce qui risque d'être un petit peu pénible. On va donc présenter un procédé permettant, un peu comme en mathématiques, de poser x
la valeur pour laquelle on veut effectuer les trois lignes de code précédentes. Une fois la valeur de x
posé, la lettre x
désignera cette valeur. Voici la démarche à suivre :
let x = (...la valeur de x...) in (...instructions utilisant x...)
Décryptons cela :
"let"
se traduit"posons"
ou encore"soit"
,"x"
est le nom de la valeur que l'on est en train de poser,- le signe
=
indique qu'on va en préciser la valeur, "in"
se traduit"dans"
ou"à l'intérieur de"
, (sous-entendu des instructions suivantes).- il n'y a pas de point-virgule après le
in
.
Concrétisons cette théorie dans l'exemple qui nous intéresse :
let x = 238 in print_int x; print_string " a pour carré "; print_int (x * x);
la valeur 238 n'apparaît plus qu'une seule fois, et on peut maintenant la changer en un seul remplacement
"let nom = ... in"
est la suivante :
- calcule la valeur de l'expression entre le signe
=
et lein
, - remplace le nom par cette valeur dans les instructions concernées,
- passe alors à l'exécution de la suite.
Remarque : on précisera plus tard les notions générales de valeurs et d'expressions.
Vérifiez qu'en appliquant la règle pas à pas, le code utilisant let x = 238
est équivalent du point de vue du comportement à celui d'origine :
print_int 238; print_string " a pour carré "; print_int (238 * 238);
En plus, on n'a plus de problème de parenthèses manquante avec les nombres négatifs, comme le montre l'exemple suivant :
let x = -12 in print_int x; print_string " a pour carré "; print_int (x * x);
On a utilisé le nom "x"
pour y associer des valeurs. On aurait très bien pu prendre comme nom n'importe quel mot satisfaisant à la condition suivante :
Un nom de valeur doit être formé de lettres de bases (de a à z ou de A à Z), de chiffres, et d'underscores (le symbole _
), et doit en outre commencer par une lettre minuscule. Il ne faut pas mettre d'espaces, ni de lettres accentuées ou tout autre caractère spécial.
Attention, après un in
, il doit toujours y avoir au moins une instruction. Écrire juste :
let x = -12 in
File "test.ml", line 1, characters 13-13: Syntax error
entraîne un message d'erreur sur le in
. La raison est qu'il ne sert à rien de faire une déclaration si on n'en fait rien du tout après.