Installation d'OCaml - Travailler en ligne - Fiche PDF MP2I 2024-2025
Document Details
Uploaded by IdyllicLogarithm
2024
Gérard Rozsavolgyi
Tags
Summary
Ce document est un tutoriel sur l'installation et l'utilisation d'OCaml. Il détaille la procédure d'installation pour différents systèmes d'exploitation et fournit des conseils pour configurer un environnement de travail en ligne. Il présente également les bases du langage OCaml et des types de données.
Full Transcript
MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Installation d’OCaml - Travailler en de bénéficier en outre de l’historique des...
MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Installation d’OCaml - Travailler en de bénéficier en outre de l’historique des commandes — https://basthon.fr ou Capytale via Moodle. ligne via les flèches haut et bas du clavier. On peut égale- ment revenir au début de ligne avec CTRL A et aller en — — https://www.france-ioi.org/index.html https://try.ocamlpro.com fin de ligne avec CTRL E. — https://ocaml.org/play Installer les outils de base — Pour l’éditeur (open source) VSCode, voir : https:// Pour tous les principaux systèmes d’exploitations , il existe marketplace.visualstudio.com/items?itemName= des distributions de OCaml : https://v2.ocaml.org/docs/ ocamllabs.ocaml-platform pour la configuration. install.html — On peut également installer un noyau OCaml pour L’installation s’effectue en deux temps : Jupyter-Notebooks : https://github.com/akabe/ ocaml-jupyter, ce qui permet de travailler dans un — Installer opam est le plus simple sous Linux ou MacOS, navigateur Web de manière assez simple. à l’aide de votre gestionnaire de paquets. Sous MacOS, — Si vous êtes utilisateur de l’éditeur Emacs, vous pou- installer d’abord un gestionnaire de paquets comme vez utiliser le mode Tuareg : Macports (https://www.macports.org/install.php) ou https://www.emacswiki.org/emacs/TuaregMode. Homebrew (https://brew.sh). Sous Windows, le plus simple est probablement d’ins- taller WSL qui vous donnera aussi accès aux même Les données et leurs types en OCaml commandes que sous Linux ou MacOS. Alternative- ment, sous tous les OS, on peut installer Multipass ou Le typage en OCaml est dit typage statique, au contraire du ty- utiliser des conteneurs Docker. page dynamique d’autres langages. La différence réside dans — Installer un switch le moment où un type est associé à chaque expression : res- Une fois opam installé, on peut installer sa ou ses pectivement avant ou pendant l’exécution. On retrouve aussi propres distributions de OCaml. le typage statique en C, par exemple dans la déclaration du Dans un terminal, commencez par lancer opam init type (le int de int x = 42;) au moment de créer une va- pour initialiser la configuration d’opam, puis on va riable. Il n’y aura pas de conversion automatique en cas d’in- choisir une version de OCaml avec opam switch compatibilité du type d’une expression avec le type attendu create 5.2.0 (version publiée en 2024). par son utilisation. Pour autant, le type d’une expression n’est Vous obtenez ainsi une version récente d’OCaml. pas forcément précis. Il est déduit en OCaml par les opéra- En cas de problèmes de compatibilité (utilisation de teurs et fonctions, entre autres, impliqués dans l’expression, notebooks notamment), on peut également installer c’est ce qu’on appelle l’inférence de type, ce qui laisse parfois le switch 4.14.2 est LTS (Long Term Support). un doute. Par exemple, la fonction identité sera de type « fonc- tion qui à une expression de type noté 'a associe un objet de type 'a » (on parle de polymorphisme). De même, l’opé- Configurer son editeur rateur de comparaison nécessite deux opérandes du même — Vous pouvez travailler directement depuis la ligne de type, mais celui-ci peut être quelconque. En particulier, on n’a commande en lançant le REPL (interpréteur) ocaml pas le droit de comparer 0 et 0.0, ce qui risque d’être un peu mais sans grandes possibilités d’édition. déstabilisant. La gestion de la mémoire en OCaml est auto- — L’éditeur le plus minimaliste que vous pouvez utiliser matique. Inutile donc de s’inquiéter avec les allocations. est l’éditeur ligne ledit. Vous pouvez l’installer aisé- En particulier, il existe un ramasse-miettes pour libérer la mé- ment via un gestionnaire de paquets sous Linux ou moire qui n’est plus utilisée. MacOS. On le lance avec : Travailler en ligne > ledit ocaml sh Quelques sites où l’on peut coder directement en OCaml en Il permet d’utiliser l’interpréteur dans un terminal et ligne : MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Les bases de OCaml 1 # max_int;; OCaml 1 # 1. +. 2.1 ;; OCaml 2 - : int = 4611686018427387903 2 - : float = 3.1 Les types de données fondamentaux 3 # min_int;; 3 # log(exp(1.));; 4 - : int = -4611686018427387904 4 - : float = 1. (on affiche ici le prompt # et la réponse de ocaml) # 2.17e-5 *. 1.18e-17;; Les entiers 5 On peut travailler avec des nombres écrits dans différentes 6 - : float = 2.5606e-22 bases. Il suffit de les faire précéder de 0b pour la notation bi- 7 # sqrt(2.);; 1 # 4 + 5;; OCaml naire, 0o pour l’octal et 0x si l’on souhaite écrire en hexadéci- 8 - : float = 1.41421356237309515 2 - : int = 9 mal : 9 # 2.**10.;; 10 - : float = 1024. OCaml détermine que le résultat de l’opération 4 + 5 est un 1 # 0b1010;; OCaml 11 # 5.0/.0.;; entier de type int. OCaml utilise ici l’inference de type, c’est- 2 - : int = 10 12 - : float = infinity à-dire qu’il déduit le type des variables utilisées et celui du 3 # 0xb;; 13 # -5.0/.0.;; résultat. 4 - : int = 11 14 - : float = neg_infinity Les priorités habituelles des opérations sont respectées. En 5 # 0xbb;; cas d’ambiguïté, un parenthésage implicite à gauche est ap- 6 - : int = 187 Mais attention, elles peuvent évidemment donner lieu à des pliqué : erreurs d’arrondi ! Les flottants 1 # 2 + 3 * 5;; OCaml # 0.1 +. 0.1 +. 0.1 -. 0.3;; OCaml Les nombres décimaux sont de type float. Ils sont représen- 1 - : int = 17 - : float = 5.5511151231257827e-17 tés en interne au format IEEE 754 avec une mantisse 𝑚 et un 2 2 # 2 - (3 + 5);; exposant 𝑛. 3 4 - : int = -6 On peut vouloir convertir un entier en flottant, il s’agit d’un. 5 # 2 - 3 + 5;; 1 # 10.;; OCaml 6 - : int = 4 # float(2) +. 2.2;; OCaml 2 - : float = 10. 1 2 - : float = 4.2 La division est entière par défaut : 3 # float 2 +. 2.2;; Les opérations entre entiers et floats ne sont pas très harmo- nieuses : 4 - : float = 4.2 1 # 11 / 3;; OCaml 2 - : int = 3 et inversement, pour passer d’un float à un int : 3 # 11 / 3*2;; 1 # 1.1 + 2;; OCaml - : int = 6 2 Error: This expression has type float but an 4 ↪ expression was expected of type int 1 # int_of_float(sqrt(2.));; OCaml 5 # 11 / (3*2);; 2 - : int = 1 6 - : int = 1 OCaml est bien discipliné et ne réalisera pas de conversion On peut utiliser mod pour obtenir le reste entier : implicite pour vous ! Vous devez expliciter votre opération, en Il existe aussi une fonction floor, distincte de int_of_float : expliquant qu’elle concerne bien les floats ce qui est un peu contraignant et alourdit la syntaxe mais permet à l’inférence 1 # floor(sqrt(3.));; OCaml 1 # 9 mod 2;; OCaml 2 - : float = 1. 2 - : int = 1 de type de fonctionner dans tous les cas. 3 # int_of_float(sqrt(3.));; 3 # 9 / 2;; 4 - : int = 1 4 - : int = 4 Attention ! 5 # floor(-.sqrt(3.));; 1 Les opérations arithmétiques impliquant les 6 - : float = -2. Enfin, sur un processeur 64 bits, les entiers sont compris entre floats doivent toutes être suivies d’un point. 7 # int_of_float(-.sqrt(3.));; −262 et 262 − 1 (plage inférieure à celle du C) 8 - : int = -1 MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Les booléens Les chaînes et les caractères 1 # let liste = [1;2;3] ;; OCaml Les string sont entourés de guillemets (double quotes) et on 2 val liste : int list = [1; 2; 3] les concatène avec ^ tandis que les char sont stockés entre 3 # 0::liste ;; — Les booléens sont true et false. simples quotes : 4 - : int list = [0; 1; 2; 3] — Les opérateurs de comparaison comme =, ==, ren- 5 # [1;2] @ [3;4];; voient des booléens. # "Hello " ^ "le Monde !";; OCaml 1 6 - : int list = [1; 2; 3; 4] — Les opérations booléennes de base sont : not, && (et) 2 - : string = "Hello le Monde !" et || (ou). 1 # 'c';; OCaml Attention ! 2 - : char = 'c' Les listes de types hétérogènes ne sont pas ad- mises ! Correspondances entre char et codes ASCII : 1 On les utilise souvent avec des fonctions ré- 1 # 17 > 2;; OCaml cursives ou List.iter ou List.map 2 - : bool = true 1 # int_of_char 'a';; OCaml 3 # 2 == 1;; 2 - : int = 97 4 - : bool = false 3 # char_of_int 97;; 5 # 17 >= 3;; 4 - : char = 'a' - : bool = true Comparaison structurelle et physique 6 7 # (5 < 2) && ( 17 > 3);; 8 - : bool = false Les tuples — L’opérateur = est l’opérateur d’égalité structurelle. Il 9 # (5 > 1) || (17 = 2);; compare deux valeurs pour évaluer si elles ont la 10 - : bool = true Entre parenthèses, ils permettent de gérer des n-uplets de même structure et les mêmes contenus. 11 # not(17 = 2);; plusieurs valeurs potentiellement hétérogènes : — L’opérateur == est l’opérateur d’égalité physique. Il 12 - : bool = true compare deux valeurs pour voir si elles occupent 1 # (1,"1",1.0,'1');; OCaml 2 - : int * string * float * char = (1, "1", le même emplacement mémoire (donc partagent la ↪ 1., '1') même valeur). 1 let a = [1; 2; 3];; OCaml Pour les comparaisons de booléens ou d’entiers, on peut uti- liser les opérateurs = ou == : Voir plus bas pour les types de Listes OCaml 2 let b = [1; 2; 3];; données plus complexes. 3 let c = a;; Il existe un type tableau (ou vecteur) comme dans de nom- 4 a = b;; (* true *) breux langages. Sa longueur est fixée lors de sa création ce qui 5 a == b;; (* false *) permet d’avoir accès à chaque composante : 6 a == c;; (* true *) 1 # let t = [|1;2;3|] ;; OCaml 1 # let x = 2;; OCaml 2 val t : int array = [|1; 2; 3|] Attention ! 2 val x : int = 2 3 # t.(2) ;; 3 # let y = 2;; 4 - : int = 3 Deux valeurs qui sont égales selon == sont 4 val y : int = 2 toujours égales selon =, mais la réciproque 5 # x = y ;; Il existe un type liste dynamique. On n’a accès en standard n’est pas nécessairement vraie. Si vous avez 6 - : bool = true qu’à son premier élément et au reste. On a cependant un opé- deux structures de données distinctes qui 1 contiennent les mêmes valeurs, elles peuvent 7 # x == y ;; rateur binaire de concaténation de listes @ (semblable au + en 8 - : bool = true Python) : être égales selon =, mais pas selon ==. MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Attention ! Création de types 1 # let (x,y) = (2.,10.) in x ** y ;; OCaml 2 - : float = 1024. La comparaison entre floats est probléma- C’est l’un des points forts d’OCaml : tique à deux titres : Pour des énumérations ou types sommes : — Tout d’abord il faut bien penser à uti- Déclarations simultanées liser les opérateurs spécialisés +., *., 1 (* Enumérations *) OCaml On utilise le mot clef and (qui aura aussi un autre usage) : etc. pour réaliser des opérations sur les 2 type couleur = # let a= 17 and b = 19;; OCaml floats. 3 Trefle | Carreau | Coeur | Pique 1 — Ensuite, les erreurs d’approximation 4 # [Trefle ; Carreau] ;; 2 val a : int = 17 sur les floats peuvent faire que les com- 5 - : couleur list = [Trefle; Carreau] 3 val b : int = 19 paraisons deux éléments de type float 4 # a + b ;; soient érronées : Notez les majuscules initiales. 5 - : int = 36 mais ausi : 1 (* Un float à problémes ! *)OCaml On peut réaliser la même chose avec des tuples, à la manière 2 # let x = 0.1 +. 0.1 +. 0.1 ;; 1 (* Enregistrements *) OCaml de Python : 3 val x : float = 2 type point = { x : float; y : float } ↪ 0.300000000000000044 1 # let (c1,c2) = ('a','b');; OCaml # let y = 0.3;; 2 val c1 : char = 'a' 4 1 (* Option *) OCaml 3 val c2 : char = 'b' 5 val y : float = 0.3 2 type 'a option = None | Some of 'a 6 # x = y;; - : bool = false Fonctions 7 8 # x == y;; 1 (* Par cas *) OCaml - : bool = false 2 type figure = 9 | Rectangle of point * point Définir une fonction 10 # x -. y;; 3 1 11 - : float = 4 | Cercle of point * float Une expression fonctionnelle est constituée d’un paramètre ↪ 5.5511151231257827e-17 formel (le nom de la variable) suivi d’un corps qui est lui même une expression licite en OCaml. Les déclarations On peut créer des fonctions avec function ou fun : let OCaml 1 # let delta = A la manière d’autres langages, comme Javascript. 2 fun (a, b,c) -> b*b - 4*a*c;; 1 # let x = 3 * 4;; OCaml 3 val delta : int * int * int -> int = 4 2 val x : int = 12 5 # delta(1,2,3);; Déclarations locales 6 - : int = -8 On peut définir localement une variable, avec une portée li- Notez que delta est bien décrite par OCaml comme une fonc- mitée à l’expression où elle a été définie : tion : 𝑖𝑛𝑡 ∗𝑖𝑛𝑡 ∗𝑖𝑛𝑡− > 𝑖𝑛𝑡 =< 𝑓𝑢𝑛 > qui indique qu’il s’agit d’une fonction de ℤ3 dans ℤ. 1 # let x = 41 in x + 1 ;; OCaml On peut également déclarer la fonction sous la forme : 2 - : int = 42 3 (* La définition est bien locale : *) 1 # let delta = fun (a,b,c) -> b*b-4*a*c;; OCaml 4 # x;; 5 Error: Unbound value x ou sous une forme plus basique : MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I 1 # let delta(a,b,c) = b*b - 4*a*c;; OCaml 1 # let xor a b = OCaml Si nous reprenons la fonction anonyme fun x -> x *. x 2 val delta : int * int * int -> int = 2 match (a, b) with carre, nous pouvons à présent calculer la dérivée approchée 3 | (true, false) -> true de cette fonction au point 𝑥 = 3 grâce aux fonctions compose avec des booléens : 4 | (false, true) -> true et carre. 5 | _ -> false;; 1 # let bissextile annee = OCaml 6 val xor : bool * bool -> bool = 1 # let carre' = deriv (fun x -> x *. x) OCaml 2 (annee mod 4 = 0 && (annee mod 100) != 0) || 7 # xor true true;; ↪ 1e-10;; ↪ (annee mod 400) = 0;; 8 - : bool = false 2 val carre' : float -> float = 3 val bissextile : int -> bool = 9 # xor true false;; 3 # carre' 3.;; 4 # bissextile(2024);; 10 - : bool = true 4 - : float = 6.00000049644222599 5 - : bool = true Ce qui semble une approximation raisonnable … Définir une fonction par cas : filtrage Fonctions : des citoyens de première classe Mais on peut également définir une fonction derivee géné- rique calculant une dérivée approchée pour une fonction 𝑓 On peut disjoindre des cas grâce au filtrage par motif ou pat- On peut tout d’abord utiliser comme en Python, Haskell, Ja- quelconque : tern matching : vascript, Java ou C++ des fonctions anonymes en OCaml : Ces fonctions sont également appelées fonction lambda ou 1 # let derivee f = deriv f 1e-5;; OCaml 1 # let trigo = function OCaml lambda function : 2 val derivee : (float -> float) -> float -> 2 | 0. -> 0.5 ↪ float = 3 | x -> (1.-.cos(x))/.(x*.x);; 1 # (fun x -> x * x );; OCaml 4 val trigo : float -> float = 2 - : int -> int = Puis l’utiliser avec la fonction carre au point 3 : 5 # trigo(0.);; 3 # (fun x -> x *. x );; 6 - : float = 0.5 4 - : float -> float = 7 # trigo(0.0001);; 1 # derivee carre 3.;; OCaml 8 - : float = 0.499999996961264515 Que l’on peut également appliquer directement : 2 - : float = 6.0000099999513159 On peut rendre le paramètre du filtrage explicite avec la syn- 1 # (fun x -> x * x )2;; OCaml puis de même définir une fonction dérivée seconde par : taxe match with : 2 - : int = 4 1 let derivee_seconde f = OCaml 1 let rec factorielle n = match n with OCaml On peut facilement passer des fonctions en paramètres à 2 derivee (derivee f);; 2 | 0 -> 1 d’autres fonctions : 3 | n -> n * factorielle (n-1);; Puis calculer la dérivée seconde en 3 de la fonction carre : 1 # let derive f dx = OCaml Et utiliser le cas par défaut (tout autre cas), signalé par un _ : 2 fun x -> (f (x +. dx) -. f x) /. dx;; 1 # derivee_seconde carre 3.;; OCaml 3 val derive : (float -> float) -> float -> - : float = 2.000017929049136 1 # let nand a b = OCaml 2 ↪ float -> float = 2 match (a, b) with 3 | (true, true) -> false Attention ! Le type un peu complexe de la fonction derive se décompose 4 | _ -> true;; de la manière suivante : Ce n’est pas une méthode très fiable pour cal- 5 val nand : bool -> bool -> bool = 6 # nand true true;; — Premier argument (float -> float) : la fonction 𝑓. culer des dérivées secondes car les erreurs 7 - : bool = false — Le deuxième argument, de type float : la valeur 𝑑𝑥. d’arrondi dans les différences finies vont se cu- — Valeur de retour de type float -> float : la valeur de 1 8 # nand false false;; muler. Par exemple avec un dx = 1e-10, on 9 - : bool = true retour de la fonction deriv est une fonction qui à un obtient un résultat erroné. float associe un float. MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I On peut à présent composer des fonctions, cette fois avec des 1 let nb_sol(a,b,c) = OCaml On peut toujours programmer en impératif types génériques : 2 let delta(a,b,c) = 3 b*b - 4*a*c 1 # let compose f g = fun x -> f (g x);; OCaml val compose : ('a -> 'b) -> ('c -> 'a) -> 'c 4 in if delta(a,b,c) = 0 then 1 Type unit 2 5 else if delta(a,b,c) < 0 then 0 ↪ -> 'b = 6 else 2;; Il existe des fonctions qui jouent le rôle dévolu aux procé- Le type de compose s’explique comme suit : dures dans les langages impératifs et qui sont à effets de — Le premier argument 𝑓 désigne ici une fonction trans- bords. Ocaml étant typé, un type est tout de même affecté à formant un type de variable 𝑎 en un type 𝑏. ces fonctions : unit. — Le second argument 𝑔 est une fonction transformant un type de variable 𝑐 en un type 𝑎. Récursion terminale — La fonction composée résultante transforme ainsi un type de variable 𝑐 en un type de variable 𝑏. 1 let rec succ = function OCaml 2 |0 -> 1 |n -> 1 + succ(n-1) ;; # print_string "Youkoulélé" ;; OCaml Conditionnelles et définitions locales 3 1 4 val succ : int -> int = 2 Youkoulélé- : unit = () On peut faire usage de structures conditionnelles pour définir 5 des fonctions : 6 # succ(100000);; 7 - : int = 100001 1 let valeur_abs(x)= OCaml 8 # succ(1000000);; 2 if x >= 0 then x 9 Stack overflow during evaluation (looping recursion?). Une autre action à effet de bord est la modification en place 3 else -x;; ↪ d’un (array) à l’aide de l’opérateur int = On arrive à la limite de la pile. Fonctions récursives C’est une fonction construite en s’invoquant elle-même. Seul 1 let succ(n) = OCaml let rec local = function 1 # let v = [|1;2;3|];; OCaml le modificateur rec après let la distingue d’une fonction or- 2 | (0,acc) -> acc 2 val v : int array = [|1; 2; 3|] dianaire : 3 4 | (n,acc) -> local(n-1,1 + acc) 3 # v.(2) 1 6 val succ : int -> int = 5 # v ;; 3 | n -> n * factorielle(n-1);; 7 6 - : int array = [|1; 2; 42|] 4 val factorielle : int -> int = 8 # succ(100000000);; 5 9 - : int = 100000001 6 let rec fact(n)= 7 if n=0 then 1 8 else n*fact(n);; Astuce val fact : int -> int = À retenir 9 OCaml est capable de dérécursiver les récur- sions terminales et n’utilise alors plus sa pile On évitera ce genre d’action à effet de bord qui ne peut donc plus être saturée. partout où c’est possible. Définition locale de fonctions MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Références Boucles Signature, curryfication et fonctions partielles Le langage Caml oblige à distinguer une référence et son 1 let module_carre (x, y) = x *. x +. y *. OCaml y;; contenu. On ne pourra ainsi pas écrire x := x + 1 comme La syntaxe est relativement usuelle mais il faut bien faire at- en C par exemple. Une référence est crée avec ref, et pour tention à la distinction référence/contenu (s / !s) et à l’af- accéder à son contenu, on doit invoquer ! : fectation des références := : La signature d’une fonction est l’information sur les types des arguments et de la valeur de retour. Elle est donnée en OCaml par la syntaxe : 1 # let x = ref 1 ;; OCaml nom : type_arg1 → type_arg2 → ⋯ → type_retour 2 val x : int ref = {contents = 1} La fonction précédente a pour signature module_carre 3 # x;; 1 (* Boucle for *) OCaml : float * float → float, et la console affiche val 4 - : int ref = {contents = 1} 2 # let sum(n) = module_carre : float * float → float =. 3 let s = ref 0 in Mais si l’on écrit : 4 for i=1 to n do Mais on ne peut pas invoquer : s := !s + i 5 1 let mod_carre x y = x *. x +. y *. y;; OCaml 6 done; 1 # x * 2 ;; OCaml 7 !s;; on obtient la signature : 8 val sum : int -> int = 2 Error: This expression has type int ref 9 # sum(100);; 1 val mod_carre : float -> float -> float = OCaml 3 but an expression was expected of type 10 - : int = 5050 ↪ int ↪ Il faut comprendre, dans cette signature, c’est qu’en fait la il faut écrire : fonction nom n’attend qu’un argument et retourne une autre fonction de signature De la même façon, on obtient une boucle while, en utilisant nom1 : type_arg2 ->... -> type_retour, pour laquelle 1 # !x * 2 ;; OCaml ici deux références s et i : le principe est le même. 2 - : int = 2 Il est donc tout à fait possible de définir une fonction partielle à partir d’une telle fonction en renseignant successivement On peut réaliser de nouvelles affectations en utilisant les ré- des arguments. férences : 1 (* Boucle While *) OCaml Tester à ce sujet le code suivant : 2 # let sum_w(n) = 3 let s = ref 0 in 1 let add x y = x + y;; OCaml 1 # x := !x + 3 ;; OCaml 4 let i = ref 0 in 2 2 - : unit = () 5 while (!i int = 13 1 let inc = ( + ) 1;; OCaml On remarque au passage qu’une réaffectation est bien 14 # sum_w(100);; du type unit. - : int = 5050 15 1 let double = ( * ) 2;; OCaml MP2I — 2024 – 2025 Fiche Memo Débuts avec OCaml - Gérard Rozsavolgyi Informatique MP2I Immutabilité en OCaml Conventions de nommage en OCaml Ouvrage de référence CAML : http://www.pps.jussieu.fr/Livres/ora/DA-OCAML/ En OCaml, lorsqu’une valeur est créée, elle ne peut pas Identificateurs (variables et fonctions) : en Un tutoriel en français : https://ocaml-tutorial.org/fr être modifiée. On parle d’immutabilité. Cela contraste avec ”snake_case” en minuscules, doivent être clairs et d’autres langages où les valeurs (ou objets) peuvent être mo- explicites, parfois au détriment de la concision. difiées après leur création, qu’on appelle mutabilité. Modules : Utilisent le ”CamelCase” avec majuscule ini- tiale comme : MyFunction, UserDetails ou Montant- Par exemple, quand on crée une liste ou un enregistrement, Total. Les noms de modules doivent être descriptifs et on ne peut pas changer les éléments de la liste ou les champs indiquer clairement ce que le module contient ou fait. de l’enregistrement en place. Si on veut une liste avec des élé- Constantes : OCaml ne distingue pas explicitement les ments modifiés ou un enregistrement avec des champs diffé- constantes des autres variables, mais on peut éven- rents, il faut créer une nouvelle liste ou un nouvel enregistre- tuellement utiliser des lettres majuscules ou un préfixe ment. pour indiquer une valeur constante. (Comme dans une librairie en C, on peut utiliser un module pour 1 let liste_ori = [1; 2; 3] OCaml grouper des constantes liées.) 2 let ma_nouvelle_liste = 0 :: liste_ori Types et variantes : Les noms de types utilisent généra- 3 (* Crée une nouvelle liste [0; 1; 2; 3] *) lement le ”snake_case”, comme les identificateurs. Les 4 (* liste_ori est inchangée *) constructeurs de variantes utilisent le ”CamelCase”, comme les modules. ou encore, pour un type enregistrement : Type de champs d’enregistrement et de noms de la- bels : Utilisent généralement le ”snake_case”. 1 type point = { x : float; y : float } OCaml Signatures et functors : Suivent généralement les 2 let p = { x = 1.0; y = 2.0 };; mêmes règles que les modules, utilisant le ”Camel- 3 let p_modifie = { p with x = 3.0 } Case”. 4 (* Crée un nouveau point avec x = 3.0 et y = Opérateurs infixes personnalisés : Doivent ↪ 2.0 *) commencer et finir par un caractère parmi ! $ % & * + -. / : < = > ? @ ^ |. Commentaires et documentation : Les commentaires doivent être clairs et concis, et apporter une informa- Définition d’opérateurs infixes tion précise. Utiliser des commentaires spéciaux ((**... *)) pour la documentation qui peut être extraite avec On peut également définir nos propres opérateurs infixes en des outils comme ocamldoc. OCaml. Par exemple, définissons un opérateur pour addition- ner deux paires : Quelques ressources intéressantes 1 # let (++) (x1, y1) (x2, y2) = OCaml Une très riche introduction à OCAML par l’un de ses 2 (x1 + x2, y1 + y2);; pères : 3 val ( ++ ) : int * int -> int * int -> int * https://caml.inria.fr/pub/distrib/books/manuel- ↪ int = cl.pdf Le manuel de référence de CAML en français, par Xa- vier LEROY et Pierre WEIS : Que l’on utilise ensuite comme ceci : http://caml.inria.fr/pub/distrib/books/manuel- cl.pdf 1 # (3, 4) ++ (5, 6);; OCaml Version plus récente en Anglais (couvrant OCaml >= 2 - : int * int = (8, 10) 5) : https://v2.ocaml.org/manual/