OCaml (, anteriormente Objective Caml) es un lenguaje de programación para propósitos generales, de alto nivel y multiparadigma que extiende el dialecto Caml de ML con características orientadas a objetos. OCaml fue creado en 1996 por Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez y otros.
La cadena de herramientas de OCaml incluye un intérprete interactivo de nivel superior, un compilador de código intermedio (bytecode), un compilador optimizado de código nativo, un depurador reversible y un gestor de paquetes (OPAM), junto con un sistema de construcción modular para OCaml (Dune). OCaml se desarrolló inicialmente en el contexto de la demostración automática de teoremas y se utiliza en software de análisis estático y métodos formales. Más allá de estas áreas, ha encontrado aplicaciones en la programación de sistemas, desarrollo web y utilidades financieras específicas, entre otros dominios.
El acrónimo CAML originalmente significaba «Lenguaje de Máquina Abstracta Categórica» (Categorical Abstract Machine Language), pero OCaml omite esta máquina abstracta. OCaml es un proyecto de software libre y de código abierto gestionado y mantenido principalmente por el Instituto Nacional de Investigación en Informática y Automática de Francia (Inria). A principios de los años 2000, elementos de OCaml fueron adoptados por muchos lenguajes, especialmente F# y Scala.
Filosofía Los lenguajes derivados de ML son más conocidos por sus sistemas de tipos estáticos y sus compiladores con inferencia de tipos. OCaml unifica la programación funcional, imperativa y orientada a objetos bajo un sistema de tipos similar al de ML. Por lo tanto, los programadores no necesitan estar profundamente familiarizados con el paradigma de lenguajes puramente funcionales para utilizar OCaml.
Al requerir que el programador trabaje dentro de las restricciones de su sistema de tipos estático, OCaml elimina muchos de los problemas relacionados con tipos runtime de ejecución asociados con lenguajes tipo dinámico. Además, el compilador con inferencia de tipos de OCaml reduce significativamente la necesidad de anotaciones de tipo manuales que son obligatorias en la mayoría de los lenguajes tipo estático. Por ejemplo, los tipos de datos de las variables y las signaturas de las funciones generalmente no necesitan declararse explícitamente, como ocurre en lenguajes como Java y C#, ya que pueden inferirse a partir de los operadores y otras funciones aplicadas a las variables y valores en el código. Aunque el uso efectivo del sistema de tipos de OCaml puede requerir cierta sofisticación por parte del programador, esta disciplina se recompensa con software confiable y de alto rendimiento.
OCaml se distingue de otros lenguajes con orígenes académicos principalmente por su énfasis en el rendimiento. Su sistema de tipos estático previene desajustes de tipo en tiempo de ejecución y, por lo tanto, elimina la necesidad de verificaciones de tipo y seguridad en tiempo de ejecución que afectan el rendimiento de los lenguajes de tipado dinámico, mientras garantiza la seguridad en tiempo de ejecución, excepto cuando se desactiva la verificación de límites de arreglos o se utilizan características inseguras, como la serialización. Estas excepciones son lo suficientemente raras como para evitarlas en la práctica.
Además de la sobrecarga de la comprobación de tipos, los lenguajes de programación funcional son, en general, difíciles de compilar a un código de máquina eficiente debido a problemas como el problema funarg. Junto con las optimizaciones estándar de bucles, registros e instrucciones, el compilador optimizador de OCaml emplea métodos de análisis estático del programa para optimizar la asignación de clausura y el empaquetamiento de valores, maximizando el rendimiento del código resultante incluso si utiliza ampliamente construcciones de programación funcional.
Xavier Leroy ha afirmado que «OCaml ofrece al menos el 50% del rendimiento de un compilador de C decente», aunque una comparación directa es imposible. Algunas funciones de la biblioteca estándar de OCaml están implementadas con algoritmos más rápidos que las funciones equivalentes en las bibliotecas estándar de otros lenguajes. Por ejemplo, la implementación de la unión de conjuntos en la biblioteca estándar de OCaml es teóricamente más eficiente que la función equivalente en las bibliotecas estándar de lenguajes imperativos (e.g., C++, Java), ya que la implementación de OCaml puede aprovechar la inmutabilidad de los conjuntos para reutilizar partes de los conjuntos de entrada en el conjunto de salida (véase estructura de datos persistente).
Historia miniaturadeimagen|El equipo de desarrollo de OCaml recibiendo un premio en el Simposio sobre Principios de Lenguajes de Programación (POPL) 2024.
Desarrollo de ML (Meta Language) Entre las décadas de 1970 y 1980, Robin Milner, un científico informático británico y ganador del Premio Turing, trabajó en el Laboratorio de Fundamentos de Ciencias de la Computación de la Universidad de Edimburgo. Milner y otros estaban trabajando en demostradores de teoremas, que históricamente se desarrollaban en lenguajes como Lisp. Milner se encontraba repetidamente con el problema de que los demostradores de teoremas intentaban afirmar que una prueba era válida combinando elementos que no constituían pruebas. Como resultado, desarrolló un metalinguaje para su Logic for Computable Functions (LCF), un lenguaje que solo permitía al usuario construir pruebas válidas gracias a su sistema de tipos polimórfico. ML se convirtió en un compilador para simplificar el uso de LCF en diferentes máquinas y, para la década de 1980, se había convertido en un sistema completo por sí mismo. ML eventualmente serviría como base para la creación de OCaml.
A principios de la década de 1980, surgieron algunos avances que llevaron al equipo Formel de INRIA a interesarse por el lenguaje ML. Luca Cardelli, profesor investigador de la Universidad de Oxford, utilizó su máquina abstracta funcional para desarrollar una implementación más rápida de ML, y Robin Milner propuso una nueva definición de ML para evitar divergencias entre las diversas implementaciones. Simultáneamente, Pierre-Louis Curien, un investigador principal de la Universidad de París Diderot, desarrolló un cálculo de combinadores categóricos y lo vinculó al cálculo lambda, lo que condujo a la definición de la máquina abstracta categórica (Categorical Abstract Machine, CAM). Guy Cousineau, investigador de la misma universidad, reconoció que esto podía aplicarse como método de compilación para ML.
Primera implementación Caml fue diseñado y desarrollado inicialmente por el equipo Formel de INRIA, dirigido por Gérard Huet. La primera implementación de Caml se creó en 1987 y se desarrolló aún más hasta 1992. Aunque el proyecto fue liderado inicialmente por Ascánder Suárez, Pierre Weis y Michel Mauny continuaron con el desarrollo después de que Suárez se retirara en 1988.
Guy Cousineau recuerda que su experiencia con la implementación de lenguajes de programación era inicialmente muy limitada y que había múltiples deficiencias que atribuye a su responsabilidad. A pesar de ello, considera que "Ascander, Pierre y Michel hicieron un trabajo realmente destacado".
Caml Light Entre 1990 y 1991, Xavier Leroy diseñó una nueva implementación de Caml basada en un intérprete de código intermedio (bytecode) escrito en C. Además, Damien Doligez desarrolló un sistema de gestión de memoria, también conocido como recolector de basura secuencial, para esta implementación. Esta nueva versión, conocida como Caml Light, reemplazó a la antigua implementación de Caml y estaba diseñada para funcionar en pequeñas computadoras de escritorio. En los años siguientes, aparecieron bibliotecas como las herramientas de manipulación de sintaxis creadas por Michel Mauny, las cuales ayudaron a promover el uso de Caml en equipos educativos y de investigación.
Caml Special Light En 1995, Xavier Leroy lanzó Caml Special Light, una versión mejorada de Caml. Se añadió un compilador optimizador de código nativo al compilador de código intermedio, lo que incrementó significativamente el rendimiento, alcanzando niveles comparables a lenguajes populares como C++. Además, Leroy diseñó un sistema de módulos de alto nivel inspirado en el sistema de módulos de Standard ML, que ofrecía potentes herramientas para la abstracción y la parametrización, facilitando el desarrollo de programas a mayor escala.
Objective Caml Didier Rémy y Jérôme Vouillon diseñaron un sistema de tipos expresivo para objetos y clases, que fue integrado en Caml Special Light. Esto dio lugar al lenguaje Objective Caml, lanzado por primera vez en 1996 y renombrado como OCaml en 2011. Este sistema de objetos soportaba muchos de los paradigmas de programación orientada a objetos de manera segura con tipos estáticos, mientras que esos mismos paradigmas causaban inconsistencias o requerían verificaciones en tiempo de ejecución en lenguajes como C++ o Java. En el año 2000, Jacques Garrigue extendió Objective Caml con múltiples características nuevas, como métodos polimórficos, variantes y argumentos etiquetados y opcionales.
Desarrollo continuo Durante las últimas dos décadas, se han añadido mejoras incrementales al lenguaje para soportar las crecientes bases de código comerciales y académicas en OCaml. La versión 4.0 de OCaml, lanzada en 2012, incorporó Tipos de Datos Algebraicos Generalizados (GADTs) y módulos de primera clase, aumentando la flexibilidad del lenguaje. La versión 5.0.0 de OCaml, lanzada en 2022, representó una reescritura completa del entorno de ejecución del lenguaje, eliminando el bloqueo global del recolector de basura (GC lock) y añadiendo controladores de efectos mediante continuaciones delimitadas. Estos cambios habilitaron el soporte para paralelismo en memoria compartida y concurrencia transparente, respectivamente.
El desarrollo de OCaml continuó en el equipo Cristal de INRIA hasta 2005, cuando fue sucedido por el equipo Gallium. Posteriormente, en 2019, Gallium fue reemplazado por el equipo Cambium. A partir de 2023, el compilador de OCaml cuenta con 23 desarrolladores principales de diversas organizaciones, mientras que el ecosistema más amplio de herramientas y paquetes de OCaml incluye a 41 desarrolladores. En 2023, el compilador de OCaml fue reconocido con el Premio al Software de Lenguajes de Programación de ACM SIGPLAN.
Características OCaml cuenta con un sistema de tipos estáticos, inferencia de tipos, polimorfismo paramétrico, recursión de cola, coincidencia de patrones, clausuras léxicas de primera clase, funtores (módulos paramétricos), manejo de excepciones, manejo de efectos y recolección automática de basura incremental generacional.
Una de las características más destacadas de OCaml es su extensión de la inferencia de tipos al sistema de objetos en un lenguaje de propósito general. Esto permite subtipado estructural, donde los tipos de objeto son compatibles si sus firmas de métodos son compatibles, independientemente de su herencia declarada, una característica poco común en lenguajes con tipado estático.
OCaml incluye una interfaz de funciones foráneas para enlazar con primitivas en C, incluyendo soporte para vectores numéricos eficientes en formatos compatibles tanto con C como con Fortran. Además, OCaml permite crear bibliotecas de funciones en OCaml que pueden enlazarse con programas principales escritos en C, lo que facilita su distribución a programadores en C sin necesidad de que estos tengan conocimientos o instalaciones de OCaml.