URL: https://linuxfr.org/news/ocaml-4-06-et-4-07 Title: OCaml 4.06 et 4.07 Authors: octachron ZeroHeure, Snark, Julien Jorge, Davy Defaud, Pierre Jarillon, Nils Ratusznik et j_m Date: 2018年06月17日T22:53:01+02:00 License: CC By-SA Tags: ocaml et langage Score: 37 La version 4.07.0 du langage OCaml a été publiée le 10 juillet 2018 soit quelques mois après la sortie de la version 4.06.0, annoncée le 3 novembre 2017. OCaml est un langage fonctionnel de la famille des langages ML (dont font partie SML et F#). Il s’agit d’un langage fonctionnel multi‐paradigme fortement typé qui permet de mélanger librement les trois paradigmes : fonctionnel, impératif et objet. ![Logo OCaml](http://ocaml.org/logo/Colour/SVG/colour-logo.svg) OCaml arrive en version 4.07 avec un tout nouvel espace de noms, `Stdlib`, pour sa bibliothèque standard. Ce nouvel espace de noms présage l’intégration progressive de nouveaux modules dans la bibliothèque standard. Un autre changement majeur, OCaml 4.06 marque la fin de la transition vers des chaînes de caractères immuables, changement amorcé dès [OCaml 4.02](https://linuxfr.org/news/ocaml-4-02#cha%C3%AEnes-de-caract%C3%A8res-immutables) . À côté de ces changements majeurs, on retrouve de nombreuses améliorations de qualité de vie : de nouveaux opérateurs d’indexation et des champs hérités pour les types objets. Mais aussi pas mal de travail de fond pour préparer l’intégration de la branche _multicore_, améliorer les passes d’optimisations Flambda, ou faire évoluer le système de types en fixant des irrégularités. ---- [OCaml 4.07.0](https://ocaml.org/releases/4.07.0.html) [OCaml 4.06.0](https://ocaml.org/releases/4.06.html) [Manuel de référence](http://caml.inria.fr/pub/docs/manual-ocaml-4.07/) [Site officiel](https://ocaml.org/) [Forum officiel](https://discuss.ocaml.org/) [Dépêche sur 4.04 et 4.05](https://linuxfr.org/news/ocaml-4-04-et-4-05) ---- # Bibliothèque standard Une des nouveautés majeures d’OCaml 4.07 est la migration de la bibliothèque standard vers un espace de noms propre `Stdlib`. Cette migration a pour principal objectif de pouvoir ajouter de nouveaux modules à la bibliothèque standard sans casser les programmes tiers. Désormais, les modules de la bibliothèque standard sont définis au sein du module `Stdlib`, module qui est ouvert par défaut par le compilateur. Ainsi, le module `List` est, par défaut, un raccourci pour `Stdlib.List`. Néanmoins, il est désormais possible de créer un module `List` sans craindre d’écraser le module `Stdlib.List` en aval : ```OCaml let trois = List.length [1;2;3] (* est désormais un raccourci pour *) let trois = Stdlib.List.length [1;2;3] (* ce qui est permet aussi d'écrire *) module List = struct ... end let trois = Stdlib.List.length [1;2;3] ``` Cette solution a d’ores et déjà permis d’ajouter deux nouveaux modules à la bibliothèque standard `Seq` et `Float`. Le nouveau module `Seq` définit un nouveau type de donnée pour des itérateurs externes, tandis que `Float` regroupe les constantes réelles et les fonctions opérant sur les `Float`. De manière similaire, la bibliothèque `Bigarray` fait désormais partie de la bibliothèque standard. Le dernier changement majeur est le basculement vers des chaînes de caractères immuables (_immutable_) par défaut dans OCaml 4.06. Ce changement avait été amorcé dans [OCaml 4.02](https://linuxfr.org/news/ocaml-4-02#cha%C3%AEnes-de-caract%C3%A8res-immutables), avec une dépréciation des fonctions manipulant le type `string` de manière mutable et une option de configuration renforçant le caractère immuable. Cette dernière option est désormais activée par défaut. # Nouveautés dans le langage ## Opérateurs d’indexation Après une [période d’incubation](https://linuxfr.org/news/ocaml-4-03#operateurs-dindexation), il est désormais possible de définir ses propres opérateurs d’indexation en dehors des types `array`, `string` et `bigarray`. C’est particulièrement utile pour manipuler des dictionnaires : ```OCaml module Dict = struct include Map.Make(String) (* importation d'un module `Map`classique *) let (.?()) dict clef = find_opt clef dict end open Dict let dict = Dict.of_seq (List.to_seq ["one", 1; "dos", 2; "drei", 3]) let trois = dict.?("drei") (* ou *) let trois = dict.Dict.?("drei") ``` Ou pour définir des formes de tableaux spécialisés sans perdre la syntaxe pratique des tableaux généralistes. Pour bien marquer la différence entre ces nouveaux opérateurs d’indexation et les opérateurs d’indexation de base, leur nom doit comporter au moins un symbole supplémentaire entre le point `.` et la parenthèse ouvrante `(`. Cependant, la syntaxe a encore besoin d’un peu de rodage pour être vraiment utilisable pour les tableaux multidimensionels des librairies de calcul numérique comme [owl](https://github.com/owlbarn/owl). ## Au monde des objets Le système objet d’OCaml a un champ d’application moins vaste que dans les langages orientés objet comme C++ ou Java. En partie parce que le système de modules répond à un grand nombre des questions de modularité et d’encapsulations qui sont le domaine des objets dans un langage purement objet. Les objets n’en demeurent pas moins utiles, et OCaml 4.06 apporte une nouvelle option pour composer plus facilement des types objets : les champs hérités. Par exemple, on peut partir d’un type animal : ```OCaml type animal = < respire: unit> ``` Ce qui définit le type d’un objet doté d’une méthode `respire` sans argument. On peut ensuite définir un type mobile : ```OCaml type mobile = < avance: int> ``` Puis combiner les deux : ```OCaml type animal_mobile = < animal; mobile> ``` Il était déjà possible d’arriver à ce résultat en jonglant avec les types de classes, mais cette nouvelle méthode est bien plus intuitive. Ce genre de code met en exergue une des particularités du système objet d’OCaml, qui est structurel : un objet n’est défini que par les méthodes qu’on peut lui envoyer et non par sa classe, ce qui donne au final un système qui s’apparente à une version statique du _duck‐typing_ à la Python. ## Meilleure intégration des types algébriques généralisés Un des travaux de fond dans OCaml 4.07 a été l’amélioration du traitement des types algébriques généralisés (ou GADT) au sein du vérificateur de types. Lors de l’introduction des GADT dans OCaml 4.00, ceux‐ci se sont souvent vus octroyés des chemins d’exécution particuliers pour séparer cette nouvelle extension du cœur mieux testé du langage. Après sept versions, les codes côté GADT et côté classique ont été unifiés. D’un point de vue utilisateur, cela signifie surtout qu’il n’est plus nécessaire de qualifier les GADT lorsque l’on filtre un schéma avec `match` : ```OCaml module M = struct type en_attente = | Fini : en_attente | En_cours : 'a * ('a -> en_attente) -> en_attente end let execute (x : M.en_attente) = match x with | Fini -> M.Fini | En_cours (x,f) -> f x ``` Alors qu’il fallait précédemment qualifier les branches du _match_ : ```OCaml let execute (x : M.en_attente) = match x with | M.Fini -> M.Fini | M.En_cours (x,f) -> f x ``` Une des nouveautés, qui concerne plus les usages avancés, est l’apparition de variants vides, c’est‐à‐dire de types de variants sans aucune valeur associée : ```OCaml type unique = | ``` Ce type étrange est principalement utile pour créer de manière explicite un nouveau type unique, qui ne sera utilisé que dans le système de type ou dans la génération de code. ## Du côté des modules Pour les utilisateurs avancés, il est désormais plus facile de préserver les alias de modules, que ce soit avec `module type of` ou des contraintes `with modules`. Par exemple, avec : ```OCaml module A = struct type t end module B = struct module Alias = A end module type S = module type of B ``` `S` est désormais équivalent à : ```OCaml module type S' = sig module Alias = A end ``` plutôt que : ```OCaml module type S_sans_alias = sig module Alias: sig type t end end ``` L’ancien comportement peut être rétabli en ajoutant un attribut `[@remove_aliases]` : ```OCaml module type S_sans_alias = module type of S [@remove_aliases] ``` Un autre changement est qu’il est désormais possible d’utiliser des substitutions destructives à l’intérieur de sous‐modules : ```OCaml module type S = sig module Inner: sig type t val x: t end end module type S' = S with type Inner.t := int ``` # Messages d’erreur Les messages d’erreur émis par OCaml ne sont pas toujours très clairs. Des efforts sont en cours pour corriger ce point. Par exemple, OCaml 4.07 essaie d’expliquer plus en détails certaines erreurs courantes chez les débutants, par exemple en cas d’oubli d’un argument `()` : ```OCaml let un () = 1 let test = (0 = un);; ``` > Error: This expression has type unit -> int but an expression was expected of type int Hint: Did you forget to provide `()' as argument? Le contexte de certaines erreurs est désormais mieux détaillé : ```OCaml let () = if () then () ``` >Error: This variant expression is expected to have type bool because it is in the condition of an if-statement plutôt que juste : > Error: This variant expression is expected to have type bool Les types faiblement polymorphiques, qui auparavant étaient marqués par juste un tiret `_`, ont maintenant des noms plus explicites : ```OCaml let none = ref None ``` > none: '_weak1 option ref Cela dans l’espoir de les rendre plus apparents et facilement cherchables, notamment dans le [manuel](http://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html#sec53). Enfin, pour les utilisateurs plus avancés, les messages d’erreurs concernant les foncteurs et modules sont passés de : ```OCaml module F() = struct end let x = F.x ``` > Error: The module F is a functor, not a structure à une version qui explique pourquoi l’extrait de code plus haut est invalide : > Error: The module F is a functor, it cannot have any components # Documentation Le [manuel de référence](http://caml.inria.fr/pub/docs/manual-ocaml-4.07/) a fait peau neuve pour la version 4.07. L’apparence graphique du manuel commençait à faire un peu daté, et un rafraîchissement de façade était de rigueur. Sur le fond, le manuel s’est enrichi d’un [nouveau chapitre](http://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html) sur les troubles liés au polymorphisme, que ce soit les types faiblement polymorphiques : ```OCaml let nouvel_identite () = fun x -> x let id = nouvel_identite () let erreur = id id ``` Le polymorphisme d’ordre supérieur : ```OCaml let f identite = identite 1, identite 2. ``` ou les fonctions polymorphiquement récursives : ```OCaml let rec etrange l = match l with | [] -> 0 | [ _ ] -> 1 | a :: q -> etrange [q];; ```

AltStyle によって変換されたページ (->オリジナル) /