OCaml, anciennement connu sous le nom d'Objective Caml, est l'implémentation la plus avancée du langage de programmation Caml, créé par Xavier Leroy, Jérôme Vouillon., , Didier Rémy. et leurs collaborateurs en 1996. Ce langage, de la famille des langages ML, est un projet open source dirigé et maintenu essentiellement par l'Inria.

OCaml est le successeur de , auquel il a ajouté entre autres une couche de programmation objet. L'acronyme CAML provient de , un modèle de machine abstraite qui n'est cependant plus utilisé dans les versions récentes de OCaml.

Portable et performant, OCaml est utilisé dans des projets aussi divers que le logiciel de synchronisation de fichiers Unison, l'assistant de preuves formelles Rocq ou la version Web de Facebook Messenger..

Il dispose d'un écosystème de développement varié, avec notamment le framework Web et mobile Ocsigen et l'unikernel MirageOS. Les facilités de traitement symbolique du langage permettent le développement d'outils de vérification statique, comme le projet SLAMQuelques succès d'OCaml : SLAM pour des pilotes Windows écrits par Microsoft, ou ASTRÉE. pour certains systèmes embarqués des Airbus A380.

Principes Caml est un langage fonctionnel augmenté de fonctionnalités permettant la programmation impérative. OCaml étend les possibilités du langage en permettant la programmation orientée objet et la programmation modulaire. Pour toutes ces raisons, OCaml entre dans la catégorie des langages multi-paradigme.

Il intègre ces différents concepts dans un système de types hérité de ML, caractérisé par un typage statique, fort et inféré.

Le système de types permet une manipulation aisée de structures de données complexes : on peut aisément représenter des types algébriques, c'est-à-dire des types hiérarchisés et potentiellement récursifs (listes, arbres…), et les manipuler aisément à l'aide du filtrage par motif. Cela fait de OCaml un langage de choix dans les domaines demandant la manipulation de structures de données complexes, par exemple les compilateurs.

Le typage fort, ainsi que l'absence de manipulation explicite de la mémoire (présence d'un ramasse-miettes) font de OCaml un langage très sûr. Il est aussi réputé pour ses performances, grâce à la présence d'un compilateur de code natif.

Histoire

Le langage Caml est né de la rencontre du langage de programmation ML, auquel s'est intéressée l'équipe Formel de l'Inria depuis le début des années 1980, et de la machine abstraite catégorique CAM de Guy Cousineau, fondée sur les travaux de Pierre-Louis Curien. en 1984. La première implémentation, écrite par Ascander Suarez (à l'époque doctorant à l'université Paris Diderot) puis maintenue par Pierre Weis et Michel Mauny, a été publiée en 1987. Le langage s'est peu à peu différencié de son père ML car l'équipe de l'Inria voulait adapter un langage à ses propres besoins, et continuer à le faire évoluer, ce qui entrait en conflit avec la « stabilité » de ML imposée par les efforts de standardisation de Standard ML.

Les limitations de la CAM ont conduit à la création d'une nouvelle implémentation, mise au point par Xavier Leroy dès 1990, sous le nom de Caml Light. Cette implémentation fonctionne grâce à un interpréteur de code octet () codé en C, ce qui lui assure une grande portabilité. Le système de gestion de la mémoire, conçu par Damien Doligez, a aussi fait son apparition dans Caml Light. En 1995, Xavier Leroy publie une version de Caml nommée , qui introduit un compilateur de code natif, et un système de modules inspiré des modules de Standard ML.

OCaml, publié pour la première fois en 1996, apporte à Caml un système objet conçu par Didier Rémy et Jérôme Vouillon. Certaines fonctionnalités avancées, comme les variantes polymorphes ou les labels (permettant de distinguer les arguments donnés à une fonction par leur nom, plutôt que leur position) ont été introduites en 2000 par Jacques Garrigue. OCaml s'est relativement stabilisé depuis (malgré l'absence d'une spécification, le document en vigueur étant le manuel officiel maintenu par l'Inriamanuel inria). De nombreux dialectes de OCaml sont apparus, et continuent d'explorer des aspects spécifiques des langages de programmation (concurrence, parallélisme, évaluation paresseuse, intégration du XML…) ; voir la section Langages dérivés.

Principales caractéristiques Langage fonctionnel OCaml possède la plupart des caractéristiques communes des langages fonctionnels, en particulier des fonctions d'ordre supérieur et fermetures (), et un bon support de la récursion terminale.

Typage Le typage statique d'OCaml détecte au moment de la compilation un grand nombre d'erreurs de programmation qui pourraient poser des problèmes au moment de l'exécution. Toutefois, contrairement à la plupart des autres langages, il n'est pas nécessaire de préciser le type des variables que l'on utilise. En effet, Caml dispose d'un algorithme d'inférence de types qui lui permet de déterminer le type des variables à partir du contexte dans lequel elles sont employées.

Le système de typage ML supporte le polymorphisme paramétrique, c'est-à-dire des types dont des parties seront indéterminées au moment de la définition de la valeur. Cette fonctionnalité, automatique, permet d'obtenir une généricité comparable à celle des de Java ou C# ou des de C++.

Cependant, les extensions du typage ML requises par l'intégration de fonctionnalités avancées, comme la programmation orientée objet, complexifient dans certains cas le système de types : l'utilisation de ces fonctionnalités peut alors demander un temps d'apprentissage au programmeur, qui n'est pas forcément familier des systèmes de types sophistiqués.

Filtrage Le filtrage par motif () est un élément essentiel du langage Caml. Il permet d'alléger le code grâce à une écriture plus souple que des conditions classiques, et l'exhaustivité fait l'objet d'une vérification : le compilateur propose un contre-exemple lorsqu'un filtrage incomplet est décelé. Par exemple, le code suivant est compilé mais il provoque un avertissement : # type etat = Actif | Inactif | Inconnu;; type etat = Actif | Inactif | Inconnu

# let est_actif = function # | Actif -> true # | Inactif -> false;; val est_actif : etat -> bool = <fun> Warning P: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: InconnuAinsi, le programme fonctionne lorsque la fonction est_actif est appelée avec un état valant Actif ou Inactif, mais s'il vaut Inconnu, la fonction renvoie l'exception Match_failure.

Modules Les modules permettent de décomposer le programme en une hiérarchie de structures contenant des types et des valeurs logiquement reliés (par exemple, toutes les fonctions de manipulation de listes vont dans le module List). Les descendants de la famille ML sont les langages ayant actuellement les systèmes de modules les plus perfectionnés, qui permettent, en plus de disposer d'espaces de noms, de mettre en œuvre l'abstraction (valeurs accessibles dont l'implémentation est cachée) et la composabilité (valeurs qui peuvent être construites par-dessus différents modules, du moment qu'ils répondent à une interface donnée).

Ainsi, les trois unités syntaxiques de construction syntaxique sont les structures, les interfaces et les modules.

Les structures contiennent l'implémentation des modules.

Les interfaces décrivent les valeurs qui en sont accessibles. Les valeurs dont l'implémentation n'est pas exposée sont des valeurs abstraites. Les valeurs qui n'apparaissent pas du tout dans l'implémentation du module sont inaccessibles, à l'instar des méthodes privées en programmation orientée objet).

Un module peut avoir plusieurs interfaces (du moment qu'elles sont toutes compatibles avec les types de l'implémentation), et plusieurs modules peuvent vérifier une même interface.

Les foncteurs sont des structures paramétrées par d'autres structures ; par exemple, les tables de hachage (module Hashtbl) de la bibliothèque standard OCaml sont utilisables comme un foncteur, qui prend en paramètre toute structure implémentant l'interface composée d'un type, d'une fonction d'égalité entre les clés, et d'une fonction de hachage.

Orienté objet OCaml se distingue particulièrement par son extension du typage ML vers un système objet comparable à ceux utilisés par les langages objets classiques. Cela permet un sous-typage structurel, dans lequel les objets sont de types compatibles si les types de leurs méthodes sont compatibles, indépendamment de leurs arbres d'héritage respectifs. Cette fonctionnalité, que l'on peut considérer comme l'équivalent du des langages dynamiques, permet une intégration naturelle des concepts objets dans un langage globalement fonctionnel.

Ainsi, à la différence des langages orientés objet tels C++ ou Java pour lesquels toute classe définit un type, les classes OCaml définissent plutôt des abréviations de types. En effet, pour peu que le type des méthodes soit compatible, deux objets de deux classes différentes peuvent être utilisés indifféremment dans un même contexte. Cette caractéristique de la couche objet de OCaml rompt bon nombre de principes communément admis : il est en effet possible de faire du sous-typage sans héritage, par exemple. Le côté polymorphe rompt le principe inverse. Des exemples de code, bien que rares, exhibant des cas d'héritage sans sous-typage existent également. La force de la couche objet tient à son homogénéité et sa parfaite intégration dans la philosophie et l'esprit même du langage OCaml. Des objets fonctionnels, dont les attributs ne peuvent être modifiés et dont les méthodes, le cas échéant, en retournent une copie avec la mise à jour des attributs, ou encore la définition d'objets immédiats, ou à la volée, sont également possibles.

Distribution La distribution OCaml contient : un interpréteur interactif (ocaml) ; un compilateur bytecode (ocamlc) et l'interpréteur de bytecode (ocamlrun) ; un compilateur natif (ocamlopt) ; des générateurs d'analyseurs lexicaux (ocamllex) et syntaxiques (ocamlyacc) ; un préprocesseur (camlp4), qui permet des extensions ou modifications de la syntaxe du langage ; un débogueur pas à pas, avec retour en arrière (ocamldebug) ; des outils de ; un générateur de documentation (ocamldoc) ; un gestionnaire de compilation automatique (ocamlbuild), depuis OCaml 3.10 ; une bibliothèque standard variée.

Les outils OCaml sont régulièrement utilisés sous Windows, GNU/Linux ou MacOS, mais existent aussi sur d'autres systèmes comme les BSD ou en ligne.

Le compilateur bytecode permet de créer des fichiers qui sont ensuite interprétés par ocamlrun. Le bytecode étant indépendant de la plate-forme, cela assure une grande portabilité (ocamlrun pouvant a priori être compilé sur toute plate-forme supportant un compilateur C fonctionnel). Le compilateur natif produit un code assembleur spécifique à la plate-forme, ce qui sacrifie la portabilité de l'exécutable produit pour des performances grandement améliorées. Un compilateur natif est présent pour les plates-formes IA-32, PowerPC, AMD64, Alpha, Sparc, Mips, IA-64, HPPA et StrongARM.

Une interface de compatibilité permet de lier du code OCaml à des primitives en C, et le format des tableaux de nombres flottants est compatible avec C et Fortran. OCaml permet aussi l'intégration de code OCaml dans un programme en C, ce qui permet de distribuer des bibliothèques OCaml à des programmeurs en C sans qu'ils aient besoin de connaître ou même d'installer OCaml.

Les outils OCaml sont majoritairement codés en OCaml, à l'exception de quelques bibliothèques et de l'interpréteur bytecode, qui sont codés en C. En particulier, le compilateur natif est entièrement codé en OCaml.

Gestion de la mémoire