Découvrir OCaml : expressions, valeurs et types
Cours · OCaml (option informatique), chapitre 1 · prépas MPSI et MP, option informatique · le début du chapitre, la suite sur Adloun
1.1 Introduction et motivation
Le tronc commun vous a appris à programmer en Python, un langage impératif : on y donne des ordres (« affecte ceci », « répète cela »), et l'on modifie pas à pas l'état de la machine. L'option informatique vous fait découvrir un second langage, OCaml, qui repose sur une idée différente et complémentaire : programmer, c'est avant tout décrire des valeurs par des expressions, et laisser la machine les évaluer. On ne dit plus tant comment faire que ce que l'on veut calculer.
Deux traits d'OCaml structureront tout ce cours. D'abord, OCaml est fortement et statiquement typé : chaque expression possède un type, vérifié par le compilateur avant toute exécution. Une bonne part des erreurs qui, en Python, ne se révèlent qu'au pire moment (sur le troisième jeu de données, le jour du concours) sont ici interceptées dès la compilation. Ensuite, ce typage est inféré : vous écrivez rarement les types vous-même, c'est le compilateur qui les reconstitue. Le compilateur cesse d'être un simple exécuteur pour devenir un relecteur exigeant et bienveillant.
Ce premier chapitre installe le socle : la boucle d'interaction et la notion d'expression, les types de base et leurs opérateurs, la liaison de noms par let et la portée lexicale, la conditionnelle vue comme une expression, les fonctions (curryfication, ordre supérieur), l'inférence de types et l'idée naïve du polymorphisme, les n-uplets, et enfin les définitions récursives. Tout ce qui suit sera supposé acquis dans les chapitres ultérieurs.
1.2 Le toplevel : tout est expression
OCaml s'utilise de deux façons complémentaires, comme Python : en mode interactif dans une boucle d'interaction (le toplevel), et en mode compilé sur un fichier .ml. Le toplevel est l'outil d'exploration idéal : on y saisit une phrase terminée par un double point-virgule ;;, et il répond en affichant le type et la valeur du résultat.
# 2 + 3;;
- : int = 5
# 7 / 2;;
- : int = 3
Une expression est un fragment de code qui se calcule (on dit s'évalue) pour produire une valeur. À toute expression bien formée, le compilateur associe un type, qui décrit la nature de la valeur produite. En OCaml, presque tout est expression : 2 + 3, x > 0, et même la conditionnelle if ... then ... else ... sont des expressions ayant chacune une valeur et un type.
La réponse du toplevel se lit toujours sur le même patron : - : <type> = <valeur> pour une expression anonyme, et val <nom> : <type> = <valeur> lorsqu'on nomme le résultat (voir la section suivante).
Le ;; est une ponctuation du toplevel, qui marque la fin d'une phrase à évaluer. Dans un fichier compilé, il est le plus souvent inutile : les définitions s'y enchaînent sans lui. Nous l'écrirons dans les sessions interactives, et l'omettrons dans les fragments de programme.
1.3 Les types de base et leurs opérateurs
1.3.1 Entiers et flottants : deux mondes séparés
OCaml distingue strictement les entiers (int) des nombres à virgule flottante (float), et — c'est sa grande surprise pour qui vient de Python — leurs opérateurs sont distincts. Sur les entiers : +, -, *, / (division entière) et mod (reste, à n'employer pour l'instant que sur des grandeurs positives). Sur les flottants, les mêmes opérateurs suivis d'un point : +., -., *., /..
# 17 mod 5;;
- : int = 2
# 3.0 *. 2.5;;
- : float = 7.5
Il n'y a en OCaml aucune conversion automatique entre int et float. L'expression 1 + 2.0 n'est pas « égale à 3.0 » : c'est une erreur de type, refusée à la compilation.
# 1 + 2.0;;
Error: This expression has type float but an expression
was expected of type int
De même, 2.0 +. 3 est refusée. On passe explicitement d'un monde à l'autre par des fonctions de conversion (vues plus loin) ; pour l'instant, on prendra l'habitude de ne pas mélanger.
Les entiers OCaml sont bornés et sujets aux dépassements de capacité : au-delà d'une certaine taille, un calcul « repasse » par les valeurs négatives au lieu de croître indéfiniment. C'est un comportement normal d'un type machine, qu'il faudra garder en tête dès qu'on manipule de grands nombres (factorielles, puissances).
Exercices du chapitre
- Portée lexicale corrigé
- Application partielle corrigé
- Fonction d'ordre supérieur et polymorphisme corrigé
- Manipuler des n-uplets corrigé
- L'algorithme d'Euclide corrigé
- Suite définie par récurrence mutuelle corrigé