# OCaml

OCaml ( /oʊˈkæməl/, 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
### 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.
Aunque OCaml no cuenta con un sistema de macros como parte indivisible del lenguaje (metaprogramación) con soporte integrado para preprocesamiento, la plataforma OCaml ofrece oficialmente una biblioteca para escribir estos preprocesadores. Existen dos tipos: uno que trabaja a nivel de código fuente (como en C) y otro que opera a nivel del árbol de sintaxis abstracta (Abstract Syntax Tree). Este último, conocido como PPX (Pre-Processor eXtension), es el recomendado.
La distribución de OCaml incluye:
* Herramientas de análisis léxico y de análisis sintáctico llamadas ocamllex y ocamlyacc.
* Depurador con soporte para retroceder y analizar errores.
* Generador de documentación.
* Perfilador para medir el rendimiento.
* Muchas bibliotecas de propósito general.
El compilador de código nativo está disponible para varias plataformas, incluyendo Unix, Microsoft Windows y Apple macOS. La portabilidad se logra gracias al soporte de generación de código nativo para arquitecturas importantes como:
* X86-64 (AMD64), RISC-V y ARM64 (en OCaml 5.0.0 y versiones superiores).
* IBM Z (antes de OCaml 5.0.0 y nuevamente en OCaml 5.1.0).
* Power (antes de OCaml 5.0.0 y programado para reaparecer en OCaml 5.2.0).
* IA-32 y ARM (antes de OCaml 5.0.0).
* SPARC (antes de OCaml 4.06.0).
* DEC Alpha, HPPA, IA64 y MIPS (antes de OCaml 4.00.0).
El compilador de código intermedio (bytecode) funciona en cualquier arquitectura de 32 o 64 bits cuando no está disponible la generación de código nativo, requiriendo únicamente un compilador en C.
Los programas en OCaml, tanto de código intermedio como de código nativo, pueden escribirse en un estilo multihilo con cambio de contexto preventivo. Los hilos de OCaml en el mismo dominio se ejecutan solo mediante compartición de tiempo. Sin embargo, un programa en OCaml puede contener múltiples dominios.

## Ejemplos de código

Los fragmentos de código en OCaml se estudian mejor introduciéndolos en el REPL (Read-Eval-Print Loop), una sesión interactiva de OCaml que muestra los tipos inferidos y los resultados de las expresiones definidas. El entorno interactivo se inicia ejecutando simplemente el programa OCaml:
El código se puede ingresar en el indicador #. Por ejemplo, para calcular 1 + 2 * 3:
OCaml infiere que el tipo de la expresión es int (un entero de precisión de máquina) y da como resultado 7.

### Hello World

El siguiente programa llamado hello.ml:
Se puede compilar a un ejecutable en código intermedio (bytecode):
O compilarlo a un ejecutable optimizado en código nativo:
Y ejecutarlo:
El primer argumento para ocamlc, "hello.ml", especifica el archivo fuente a compilar, mientras que el indicador "-o hello" especifica el archivo de salida.

### Option

El constructor de tipo option en OCaml, similar al tipo Maybe en Haskell, extiende un tipo de datos dado para devolver Some (un valor del tipo especificado) o None. Esto expresa que un valor puede o no estar presente.
Este es un ejemplo de una función que extrae un int de una opción (option). Si contiene un valor, lo convierte en una cadena de caracteres; si no, retorna una cadena vacía:

### Sumando una lista de enteros

Las listas son uno de los tipos de datos fundamentales en OCaml. El siguiente ejemplo de código define una función recursiva llamada sum que acepta un argumento, integers, que debe ser una lista de enteros. Observa la palabra clave rec, que indica que la función es recursiva. La función itera recursivamente sobre la lista de enteros proporcionada y calcula la suma de sus elementos. La instrucción match tiene ciertas similitudes con el elemento switch de C, aunque es mucho más general.
Otra forma es usar la función estándar fold, que trabaja con listas.
Dado que la función anónima es simplemente la aplicación del operador +, esto se puede simplificar a:
Además, se puede omitir el argumento de la lista utilizando una aplicación parcial:

### Quicksort

OCaml puede expresar de manera concisa algoritmos recursivos. El siguiente ejemplo de código implementa un algoritmo similar al quicksort, que ordena una lista en orden ascendente.
O usando la aplicación parcial del operador >=.

### Paradoja del cumpleaños

El siguiente programa calcula el número mínimo de personas en una sala para que la probabilidad de que todas tengan cumpleaños únicos sea menor al 50% (el problema del cumpleaños). Para 1 persona, la probabilidad es 365/365 (100%); para 2, es 364/365; para 3, es 364/365 × 363/365, y así sucesivamente. La respuesta es 23.

### Codificación de Church

El siguiente código define una codificación de Church de números naturales, junto con las operaciones de sucesor (succ) y suma (add). Un número de Church n es una función de orden superior que acepta una función f y un valor x, y aplica f a x exactamente x veces. Para convertir un número de Church en una representación de cadena, se le pasa una función que agrega el prefijo "S" a su entrada y la cadena constante "0".

### Función factorial de precisión arbitraria (biblioteca)

OCaml ofrece acceso directo a una variedad de bibliotecas, incluidas aquellas para realizar cálculos de precisión arbitraria. Dado que la función factorial crece rápidamente y supera rápidamente los límites de precisión de los números de máquina (normalmente de 32 o 64 bits), es un buen ejemplo para ilustrar el uso de aritmética de precisión arbitraria.
En OCaml, el módulo Num (ahora reemplazado por el módulo ZArith) proporciona soporte para cálculos de precisión arbitraria. Este módulo puede cargarse en un top-level interactivo con el siguiente comando:
La función factorial se puede escribir utilizando los operadores numéricos de precisión arbitraria =/, */ y -/:
Esta función puede calcular factoriales mucho más grandes, como 120!:

### Triángulo (gráficos)

El siguiente programa renderiza un triángulo rotatorio en 2D utilizando OpenGL:
Se requieren los enlaces de LablGL para OpenGL. El programa puede ser compilado a bytecode con:
O con el código nativo:
O, simplemente, utilizar el comando de construcción de ocamlfind:
Y ejecutar:
Se pueden desarrollar programas gráficos 2D y 3D mucho más sofisticados y de alto rendimiento en OCaml. Gracias al uso de OpenGL y OCaml, los programas resultantes pueden ser multiplataforma, compilando sin ningún cambio en muchas plataformas principales.

### Sucesión de Fibonacci

El siguiente código calcula la sucesión de Fibonacci de un número n ingresado. Utiliza recursión de cola y coincidencia de patrones.

### Funciones de orden superior

Las funciones pueden recibir funciones como entrada y devolver funciones como resultado. Por ejemplo, aplicar la función twice a una función f genera una función que aplica f dos veces a su argumento.
La función twice utiliza una variable de tipo 'a para indicar que puede aplicarse a cualquier función f que mapee de un tipo 'a a sí mismo, en lugar de estar restringida solo a funciones de tipo int -> int. En particular, twice incluso puede aplicarse a sí misma.

## Lenguajes derivados
### MetaOCaml

MetaOCaml es una extensión de programación de múltiples etapas de OCaml que permite la compilación incremental de nuevo código máquina durante el tiempo de ejecución. Bajo ciertas circunstancias, es posible obtener aumentos significativos de velocidad utilizando programación de múltiples etapas, porque se dispone de información más detallada sobre los datos a procesar en tiempo de ejecución que en el tiempo de compilación regular, por lo que el compilador incremental puede optimizar muchos casos de comprobación de condiciones, etc.
Como ejemplo: si en tiempo de compilación se sabe que una función de potencia x -> x^nse necesitará con frecuencia, pero el valor de n solo se conoce en tiempo de ejecución, se puede utilizar una función de potencia de dos etapas en MetaOCaml.
Tan pronto como se conozca n en tiempo de ejecución, se puede crear una función de potencia especializada y muy rápida.
El resultado es:
La nueva función se compila automáticamente.

### Otros lenguajes derivados

* F# es un lenguaje del marco .NET basado en OCaml.
* JoCaml integra construcciones para desarrollar programas concurrentes y distribuidos.
* Reason es una sintaxis y una cadena de herramientas alternativa para OCaml creada en Facebook, que puede compilar tanto a código nativo como a JavaScript.

## Software escrito en OCaml

* Ahrefs, un software de SEO.
* Alt-Ergo, un solucionador SMT.
* Astrée, un analizador estático.
* Be Sport, una red social.
* Coccinelle, una herramienta para transformar el código fuente de programas en C.
* Coq, un sistema de gestión de pruebas formales.
* Easycrypt, un conjunto de herramientas para escribir pruebas asistidas por computadora.
* F*, un lenguaje de programación de alto nivel, multiparadigma, funcional y orientado a objetos destinado a la verificación de programas.
* FFTW, una biblioteca para calcular transformadas de Fourier discretas. Varias rutinas en C han sido generadas por un programa OCaml llamado genfft.
* La versión web de Facebook Messenger.
* Flow, un analizador estático creado en Facebook que infiere y verifica tipos estáticos para JavaScript.
* Ocsigen, un marco de desarrollo web y móvil cliente-servidor.
* Owl Scientific Computing, un sistema dedicado a la computación científica e ingeniería.
* Frama-C, un marco para analizar programas en C.
* GeneWeb, un software de genealogía multiplataforma, libre y de código abierto.
* El compilador del lenguaje de programación Hack, creado en Facebook, que extiende PHP con tipos estáticos.
* El compilador del lenguaje de programación Haxe.
* HOL Light, un asistente de pruebas formales.
* Infer, un analizador estático creado en Facebook para Java, C, C++, y Objective-C, utilizado para detectar errores en aplicaciones de iOS y Android.
* Liquidsoap, un lenguaje script para generar transmisiones multimedia.
* MirageOS, un marco de programación de unikernels escrito en OCaml puro.
* MLdonkey, una aplicación de intercambio de archivos entre pares basada en la red eDonkey.
* Opa, un lenguaje de programación libre y de código abierto para el desarrollo web.
* Reason / ReScript, un lenguaje de programación de propósito general, de alto nivel, multiparadigma, funcional y orientado a objetos.
* El compilador de Rust se implementó inicialmente en OCaml antes de volverse autohospedado.
* Tezos, una plataforma de contratos inteligentes autoadaptativos que utiliza XTZ como moneda nativa.
* Unison, un programa de sincronización de archivos para sincronizar archivos entre dos directorios.
* El intérprete de referencia para WebAssembly, un bytecode de bajo nivel destinado a ejecutarse dentro de los navegadores web.
* Xen Cloud Platform (XCP), una solución de virtualización llave en mano para el hipervisor Xen.

## Usuarios

Al menos varias docenas de empresas usan OCaml en algún grado. Ejemplos notables incluyen:
* Bloomberg L.P., que creó BuckleScript, un backend de compilador OCaml dirigido a JavaScript.
* Citrix Systems, que usa OCaml en XenServer (rebautizado como Citrix Hypervisor en 2018).
* Facebook, que desarrolló Flow, Hack, Infer, Pfff y ReasonML en OCaml.
* Jane Street Capital, una firma de trading propietaria, que adoptó OCaml como su lenguaje preferido en su inicio y continúa usándolo en 2023.
* Docker, que usa OCaml en las ediciones de escritorio en macOS y Windows.
En el contexto de la enseñanza e investigación académica, OCaml tiene una presencia destacada en los programas de enseñanza de ciencias de la computación, tanto en universidades como en colegios. Una lista de recursos educativos y estos programas de enseñanza se pueden encontrar en ocaml.org.