De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda

OCaml ( / k æ m əl / OH- KAM -əl , anteriormente Caml Objetivo ) es una de propósito general , lenguaje de programación multi-paradigma que se extiende la Caml dialecto del ML con orientación a objetos características. OCaml fue creado en 1996 por Xavier Leroy , Jérôme Vouillon, Damien Doligez , Didier Rémy, Ascánder Suárez y otros.

El OCaml cadena de herramientas incluye un sistema interactivo de alto nivel intérprete , un código de bytes compilador , una optimización de código nativo compilador, un reversibles depurador , y un gestor de paquetes (OPAM). OCaml se desarrolló inicialmente en el contexto de la demostración automatizada de teoremas y tiene una presencia enorme en el software de análisis estático y métodos formales . Más allá de estas áreas, ha encontrado un uso serio en programación de sistemas , desarrollo web e ingeniería financiera , entre otros dominios de aplicaciones.

El acrónimo CAML originalmente significaba Categorical Abstract Machine Language , pero OCaml omite esta máquina abstracta . [2] OCaml es un proyecto de software gratuito y de código abierto gestionado y mantenido principalmente por el Instituto Francés de Investigación en Ciencias de la Computación y Automatización (INRIA). A principios de la década de 2000, muchos lenguajes adoptaron elementos de OCaml, en particular F # y Scala .

Filosofía [ editar ]

Los lenguajes derivados de ML son más conocidos por sus sistemas de tipos estáticos y compiladores de inferir tipos . OCaml unifica la programación funcional , imperativa y orientada a objetos en un sistema de tipo similar al ML. Por lo tanto, los programadores no necesitan estar muy familiarizados con el paradigma del lenguaje funcional puro para usar OCaml.

Al requerir que el programador trabaje dentro de las limitaciones de su sistema de tipos estáticos, OCaml elimina muchos de los problemas de tiempo de ejecución relacionados con los tipos asociados con los lenguajes de tipos dinámicos. Además, el compilador de inferencia de tipos de OCaml reduce en gran medida la necesidad de las anotaciones de tipos manuales que se requieren en la mayoría de los lenguajes de tipo estático. Por ejemplo, el tipo de datos de las variables y la firma de las funciones generalmente no necesitan declararse explícitamente, como ocurre en lenguajes como Java y C #., porque pueden inferirse de los operadores y otras funciones que se aplican a las variables y otros valores del código. El uso eficaz del sistema de tipos de OCaml puede requerir cierta sofisticación por parte de un programador, pero esta disciplina se ve recompensada con un software confiable y de alto rendimiento.

OCaml se distingue quizás más de otros idiomas con orígenes en la academia por su énfasis en el desempeño. Su sistema de tipo estático evita los desajustes de tipos en tiempo de ejecución y, por lo tanto, evita las comprobaciones de seguridad y el tipo de tiempo de ejecución que sobrecargan el rendimiento de los lenguajes tipados dinámicamente, al tiempo que garantiza la seguridad del tiempo de ejecución, excepto cuando la verificación de los límites de la matriz está desactivada o cuando se utilizan algunas características no seguras como la serialización. . Estos son lo suficientemente raros como para evitarlos en la práctica.

Aparte de la sobrecarga de verificación de tipos, los lenguajes de programación funcionales son, en general, difíciles de compilar en un código de lenguaje de máquina eficiente, debido a problemas como el problema de funarg . Junto con bucle estándar, registro, e instrucción optimizaciones , compilador de optimización de OCaml emplea análisis estático de software métodos para optimizar el valor de boxeo y el cierre de la asignación, que ayuda a maximizar el rendimiento del código resultante incluso si se hace un amplio uso de construcciones de programación funcionales.

Xavier Leroy ha declarado que "OCaml ofrece al menos el 50% del rendimiento de un compilador de C decente", [3] aunque una comparación directa es imposible. Algunas funciones de la biblioteca estándar OCaml se implementan 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 en teoría es asintóticamente más rápida que la función equivalente en las bibliotecas estándar de lenguajes imperativos (por ejemplo, C ++, Java) porque la implementación de OCaml explota la inmutabilidad de los conjuntos para reutilizar partes de la entrada. conjuntos en la salida (ver estructura de datos persistentes ).

Funciones [ editar ]

OCaml presenta un sistema de tipo estático , inferencia de tipo , polimorfismo paramétrico , recursividad de cola , coincidencia de patrones , cierres léxicos de primera clase , functores (módulos paramétricos) , manejo de excepciones y recolección de basura automática generacional incremental .

OCaml se destaca por extender la inferencia de tipos de estilo ML a un sistema de objetos en un lenguaje de propósito general. Esto permite la tipificación estructural , donde los tipos de objetos son compatibles si las firmas de sus métodos son compatibles, independientemente de su herencia declarada (una característica inusual en los lenguajes de tipificación estática).

Se proporciona una interfaz de función externa para vincular a primitivas de C , incluido el soporte de lenguaje para matrices numéricas eficientes en formatos compatibles con C y Fortran . OCaml también admite la creación de bibliotecas de funciones OCaml que se pueden vincular a un programa principal en C, de modo que una biblioteca OCaml se puede distribuir a programadores de C que no tienen conocimiento o instalación de OCaml.

La distribución OCaml contiene:

  • El análisis léxico y análisis sintáctico herramientas llamadas ocamllex y ocamlyacc
  • Depurador que admite retroceder para investigar errores
  • Generador de documentación
  • Profiler : para medir el rendimiento
  • Muchas bibliotecas de uso general

El compilador de código nativo está disponible para muchas plataformas, incluidas Unix , Microsoft Windows y Apple macOS . La portabilidad se logra mediante el soporte de generación de código nativo para las principales arquitecturas: IA-32 , X86-64 (AMD64), Power , SPARC , ARM y ARM64 . [4]

Los programas de código de bytes y código nativo OCaml se pueden escribir en un estilo multiproceso , con cambio de contexto preventivo. Sin embargo, debido a que el recolector de basura del sistema INRIA OCaml (que es la única implementación completa disponible actualmente del lenguaje) no está diseñado para la concurrencia, el multiprocesamiento simétrico no es compatible. [5] Los subprocesos OCaml en el mismo proceso se ejecutan solo por tiempo compartido. Sin embargo, existen varias bibliotecas para computación distribuida como Functory y ocamlnet / Plasma .

Entorno de desarrollo [ editar ]

Desde 2011, se han aportado muchas herramientas y bibliotecas nuevas al entorno de desarrollo de OCaml:

  • Herramientas de desarrollo
    • opam es un administrador de paquetes para OCaml, desarrollado por OCamlPro .
    • Merlin proporciona una funcionalidad similar a IDE para varios editores, incluidos retroceso de tipos, ir a la definición y autocompletar.
    • Dune es un sistema de compilación componible para OCaml.
    • OCamlformat es un formateador automático para OCaml.
  • Sitios web:
    • OCaml.org es el sitio principal del idioma.
    • discus.ocaml.org es una instancia de Discourse que sirve como el sitio de discusión principal para OCaml.
  • Compiladores alternativos para OCaml:
    • js_of_ocaml, desarrollado por el equipo de Ocsigen , es un compilador de optimización de OCaml a JavaScript .
    • BuckleScript , que también se dirige a JavaScript , con un enfoque en producir una salida de JavaScript idiomática y legible.
    • ocamlcc es un compilador de OCaml a C, para complementar el compilador de código nativo para plataformas no compatibles.
    • OCamlJava, desarrollado por INRIA, es un compilador de OCaml para la máquina virtual Java (JVM).
    • OCaPic, desarrollado por Lip6, es un compilador OCaml para microcontroladores PIC .

Ejemplos de código [ editar ]

Los fragmentos de código OCaml se estudian más fácilmente ingresándolos en el nivel superior . Esta es una sesión OCaml interactiva que imprime los tipos inferidos de expresiones resultantes o definidas. El nivel superior de OCaml se inicia simplemente ejecutando el programa OCaml:

$ ocaml  Objective Caml versión 3.09.0 #

A continuación, se puede ingresar el código en el indicador "#". Por ejemplo, para calcular 1 + 2 * 3:

# 1 + 2 * 3 ;; -: int = 7

OCaml infiere que el tipo de expresión es "int" (un entero de precisión de máquina ) y da el resultado "7".

Hola mundo [ editar ]

El siguiente programa "hello.ml":

print_endline  "¡Hola mundo!"

se puede compilar en un ejecutable de bytecode:

$ ocamlc hello.ml -o hola

o compilado en un ejecutable de código nativo optimizado:

$ ocamlopt hola.ml -o hola

y ejecutado:

$ ./hello ¡Hola mundo! PS

El primer argumento de ocamlc, "hello.ml", especifica el archivo fuente a compilar y el indicador "-o hello" especifica el archivo de salida. [6]

Sumar una lista de números enteros [ editar ]

Las listas son uno de los tipos de datos fundamentales en OCaml. El siguiente ejemplo de código define una función recursiva suma que acepta un argumento, enteros , que se supone que es una lista de enteros. Tenga en cuenta la palabra clave recque denota que la función es recursiva. La función itera de forma recursiva sobre la lista dada de enteros y proporciona una suma de los elementos. La declaración de coincidencia tiene similitudes con el elemento switch de C , aunque es mucho más general.

let  rec  suma  enteros  =  (* palabra clave rec significa 'recursivo'. *)  emparejar  enteros  con  |  []  ->  0  (* Rendimiento 0 si los números enteros son la  lista  vacía []. *) |  primero  ::  descanso  ->  primero  +  suma  descanso ;;  (* Llamada recursiva si los enteros son una  lista no vacía; el primero es el primer  elemento de la lista, y el resto es una  lista del resto de los elementos, posiblemente []. *)
 #  suma  [ 1 ; 2 ; 3 ; 4 ; 5 ] ;;  -  :  int  =  15

Otra forma es utilizar la función de plegado estándar que funciona con listas.

deje que  sumar  enteros  =  Lista . fold_left  ( divertido  acumulador  x  ->  acumulador  +  x )  0  enteros ;;
 #  suma  [ 1 ; 2 ; 3 ; 4 ; 5 ] ;;  -  :  int  =  15

Dado que la función anónima es simplemente la aplicación del operador +, esto se puede abreviar a:

deje que  sumar  enteros  =  Lista . fold_left  (+)  0  enteros

Además, se puede omitir el argumento de lista haciendo uso de una aplicación parcial :

let  sum  =  List . fold_left  (+)  0

Clasificación rápida [ editar ]

OCaml se presta para expresar de manera concisa algoritmos recursivos. El siguiente ejemplo de código implementa un algoritmo similar a quicksort que ordena una lista en orden creciente.

 deje  rec  qsort  =  función  |  []  ->  []  |  pivot  ::  rest  ->  let  is_less  x  =  x  <  pivot  in  let  left ,  right  =  List . partición  is_less  resto  en  qsort  izquierda  @  [ pivote ]  @  qsort  derecha

Problema de cumpleaños [ editar ]

El siguiente programa calcula la menor cantidad de personas en una habitación para quienes la probabilidad de cumpleaños completamente únicos es menor al 50% (el problema de cumpleaños , donde para 1 persona la probabilidad es 365/365 (o 100%), para 2 es 364/365, para 3 es 364/365 × 363/365, etc.) (respuesta = 23).

deje  year_size  =  365 .let  rec  birthday_paradox  prob  people  =  let  prob  =  ( year_size  -.  float  people )  /.  tamaño_año  *.  prob  in  si  prob  <  0 . 5  luego  Printf . printf  "respuesta =% d \ n "  ( personas + 1 )  else  birthday_paradox  prob  ( personas + 1 ) ;;birthday_paradox  1 . 0  1

Números de la iglesia [ editar ]

El siguiente código define una codificación Church de números naturales , con sucesor (succ) y adición (add). Un numeral de la Iglesia nes una función de orden superior que acepta una función fy un valor xy se aplica fa tiempos xexactos n. Para convertir un número de Church de un valor funcional a una cadena, le pasamos una función que antepone la cadena "S"a su entrada y la cadena constante "0".

deje  cero  f  x  =  x deje  succ  n  f  x  =  f  ( n  f  x ) deje  uno  =  succ  cero deje  dos  =  succ  ( succ  cero ) deje  sumar  n1  n2  f  x  =  n1  f  ( n2  f  x ) deje  to_string  n  =  n  ( divertido  k  ->  "S"  ^  k)  "0" let  _  =  to_string  ( suma  ( succ  dos )  dos )

Función factorial de precisión arbitraria (bibliotecas) [ editar ]

Se puede acceder directamente a una variedad de bibliotecas desde OCaml. Por ejemplo, OCaml tiene una biblioteca incorporada para aritmética de precisión arbitraria . A medida que la función factorial crece muy rápidamente, desborda rápidamente los números de precisión de la máquina (generalmente 32 o 64 bits). Por tanto, el factorial es un candidato adecuado para la aritmética de precisión arbitraria.

En OCaml, el módulo Num (ahora reemplazado por el módulo ZArith) proporciona aritmética de precisión arbitraria y se puede cargar en un nivel superior en ejecución usando:

#  # ##use "topfind";; #require "num";; open Num;;

La función factorial se puede escribir usando los operadores numéricos de precisión arbitraria = / , * / y - /  :

#  sea  rec  fact  n  =  si  n  = /  Int  0  entonces  Int  1  else  n  * /  fact ( n  - /  Int  1 ) ;; hecho val  : Num . num -> Num . num = < diversión >      

Esta función puede calcular factoriales mucho más grandes, como 120 !:

#  string_of_num  ( hecho  ( Int  120 )) ;; -  :  string  = "6689502913449127057588118054090372586752746333138029810295671352301633 55724496298936687416527198498130815763789321409055253440858940812185989 84811143896500059966490000"

Triángulo (gráficos) [ editar ]

El siguiente programa renderiza un triángulo giratorio en 2D usando OpenGL :

let  ()  =  ignorar  ( Glut . init  Sys . argv );  Glut . initDisplayMode  ~ double_buffer : true  () ;  ignorar  ( Glut . createWindow  ~ título : "Demo de OpenGL" );  sea ​​el  ángulo  t  =  10 .  *.  t  *.  t  en  let  render  ()  =  GlClear . claro  [  ` color ];  GlMat . load_identity  () ;  GlMat . Girar  ~ ángulo :  ( ángulo  ( Sys . tiempo  () ))  ~ z : 1 .  () ;  GlDraw . comienza  ` triángulos ;  Lista . iter  GlDraw . vértice2  [- 1. ,  - 1 .;  0. ,  1 .;  1. ,  - 1. ]; GlDraw . termina  () ;  Glut . swapBuffers  ()  en  GlMat . modo  ` modelview ;  Glut . displayFunc  ~ cb : render ;  Glut . idleFunc  ~ cb :( Some  Glut . postRedisplay );  Glut . mainLoop  ()

Se requieren los enlaces de LablGL a OpenGL. A continuación, el programa se puede compilar en código de bytes con:

 $ ocamlc -I + lablGL lablglut.cma lablgl.cma simple.ml -o simple

o al código nativo con:

 $ ocamlopt -I + lablGL lablglut.cmxa lablgl.cmxa simple.ml -o simple

o, más simplemente, usando el comando build de ocamlfind

 $ ocamlfind opt simple.ml -package lablgl.glut -linkpkg -o simple

y correr:

 $ ./simple

En OCaml se pueden desarrollar programas gráficos 2D y 3D mucho más sofisticados y de alto rendimiento. Gracias al uso de OpenGL y OCaml, los programas resultantes pueden ser multiplataforma, compilando sin cambios en muchas de las plataformas principales.

Secuencia de Fibonacci [ editar ]

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

deje  fib  n  =  deje  rec  fib_aux  m  a  b  =  emparejar  m  con  |  0  ->  a  |  _  ->  fib_aux  ( m  -  1 )  b  ( a  +  b )  en  fib_aux  n  0  1

Funciones de orden superior [ editar ]

Las funciones pueden tomar funciones como funciones de entrada y de retorno como resultado. Por ejemplo, aplicar dos veces a una función f produce una función que aplica f dos veces a su argumento.

sea  dos veces  ( f  :  ' a  ->  ' a )  =  fun  ( x  :  ' a )  ->  f  ( f  x ) ;; sea  inc  ( x  :  int )  :  int  =  x  +  1 ;; deje  add2  =  dos veces  inc ;; deje  inc_str  ( x  :  cadena )  :  cadena  =  x  ^ ""  ^  x ;; let  add_str  =  dos veces ( inc_str ) ;;
 #  add2  98 ;;  -  :  int  =  100 # add_str "Prueba" ;; - : string = "Prueba Prueba Prueba Prueba"        

La función usa dos veces una variable de tipo 'a para indicar que se puede aplicar a cualquier función f mapeando desde un tipo ' a a sí misma, en lugar de solo a funciones int-> int . En particular, incluso se puede aplicar dos veces a sí mismo.

 #  sea  cuatro  veces f  =  ( dos  veces dos veces )  f ;;  val  fourtimes  :  ( ' a  ->  ' a )  ->  ' a  ->  ' a  =  < fun > # let add4 = fourtimes inc ;; val add4 : int -> int = < fun > # add4 98 ;; - : int =                      102

Idiomas derivados [ editar ]

MetaOCaml [ editar ]

MetaOCaml [7] es una extensión de programación de varias etapas de OCaml que permite la compilación incremental de nuevo código de máquina durante el tiempo de ejecución. En algunas circunstancias, son posibles aceleraciones significativas mediante la programación de varias etapas, porque hay disponible información más detallada sobre los datos a procesar en tiempo de ejecución que en el tiempo de compilación normal, por lo que el compilador incremental puede optimizar muchos casos de verificación de condiciones, etc.

Por ejemplo: si en el momento de la compilación se sabe que a menudo se necesita alguna función de potencia , pero el valor de solo se conoce en tiempo de ejecución, se puede utilizar una función de potencia de dos etapas en MetaOCaml:x -> x^nn

 sea  rec  power  n  x  =  si  n  =  0  entonces  . < 1 >.  de lo contrario,  si  incluso  n,  entonces  sqr  ( potencia  ( n / 2 )  x )  else  . <. ~ x  *.  . ~ ( potencia  ( n  -  1 )  x )>.

Tan pronto como nse conozca en tiempo de ejecución, se puede crear una función de potencia especializada y muy rápida:

 . < fun  x  ->  . ~ ( potencia  5.  < x >.)>.

El resultado es:

 fun  x_1  ->  ( x_1  *  deje  y_3  =  deje  y_2  =  ( x_1  *  1 )  en  ( y_2  *  y_2 )  en  ( y_3  *  y_3 ))

La nueva función se compila automáticamente.

Otros lenguajes derivados [ editar ]

  • AtomCaml proporciona una primitiva de sincronización para la ejecución atómica (transaccional) de código.
  • Emily (2006) es un subconjunto de OCaml 3.08 que utiliza un verificador de reglas de diseño para hacer cumplir los principios de seguridad del modelo de capacidad de objeto .
  • F # es un lenguaje de .NET Framework basado en OCaml.
  • Fresh OCaml facilita la manipulación de nombres y carpetas.
  • GCaml agrega polimorfismo extensional a OCaml, lo que permite la sobrecarga y la clasificación con seguridad de tipos.
  • JoCaml integra construcciones para desarrollar programas concurrentes y distribuidos.
  • OCamlDuce amplía OCaml con características como expresiones XML y tipos de expresiones regulares.
  • OCamlP3l es un sistema de programación paralelo basado en OCaml y el lenguaje P3L.
  • Si bien no es realmente un lenguaje separado, Reason es una sintaxis OCaml alternativa y una cadena de herramientas para OCaml creada en Facebook .

Software escrito en OCaml [ editar ]

  • 0install , un administrador de paquetes multiplataforma.
  • Coccinelle , una utilidad para transformar el código fuente de programas en C.
  • Coq , un sistema formal de gestión de pruebas .
  • FFTW , una biblioteca para calcular transformadas discretas de Fourier . Varias rutinas C han sido generadas por un programa OCaml llamado genfft.
  • La versión web de Facebook Messenger . [8]
  • Flow, un analizador estático creado en Facebook que infiere y comprueba los tipos estáticos de JavaScript . [9]
  • Owl Scientific Computing , un sistema dedicado para la informática científica y de ingeniería.
  • Frama-C , un marco para analizar programas C.
  • GeneWeb , software de genealogía multiplataforma gratuito y de código abierto.
  • El compilador del lenguaje de programación Hack , creado en Facebook, ampliando PHP con tipos estáticos.
  • El compilador del lenguaje de programación Haxe .
  • HOL Light , asistente formal de pruebas.
  • Infer, un analizador estático creado en Facebook para Java , C, C ++ y Objective-C , que se utiliza para detectar errores en aplicaciones de iOS y Android . [10]
  • Lexifi Apropos , un sistema para modelar derivadas complejas.
  • MirageOS , un marco de programación unikernel escrito en OCaml puro.
  • MLdonkey , una aplicación para compartir archivos de igual a igual basada en la red EDonkey .
  • Ocsigen , un marco web OCaml .
  • Opa , un lenguaje de programación gratuito y de código abierto para desarrollo web.
  • pyre-check, un verificador de tipos para Python creado en Facebook. [11]
  • Tezos , una plataforma de contratos inteligentes auto-modificables que utiliza XTZ como moneda nativa.
  • Al unísono , una sincronización de archivos programa para sincronizar archivos entre dos directorios.
  • El intérprete de referencia para WebAssembly , un bajo nivel de código de bytes destinado para su ejecución dentro de los navegadores web . [12]
  • Xen Cloud Platform (XCP), una solución de virtualización llave en mano para el hipervisor Xen .

Usuarios [ editar ]

Varias docenas de empresas utilizan OCaml hasta cierto punto. [13] Ejemplos notables incluyen:

  • Bloomberg LP , que creó BuckleScript , un backend compilador OCaml dirigido a JavaScript. [14]
  • Citrix Systems , que utiliza OCaml en XenServer (rebautizado como Citrix Hypervisor durante 2018).
  • Facebook , que desarrolló Flow, Hack, Infer, Pfff y Reason en OCaml.
  • Jane Street Capital , una empresa comercial propietaria , que adoptó OCaml como su idioma preferido en sus inicios. [15]
  • MEDIT, Francia , utiliza OCaml para bioformatics. [dieciséis]

Referencias [ editar ]

  1. ^ "Módulos" . Consultado el 22 de febrero de 2020 .
  2. ^ "Una historia de OCaml" . Consultado el 24 de diciembre de 2016 .
  3. ^ Noticias semanales de Linux .
  4. ^ "ocaml / asmcomp en el tronco · ocaml / ocaml · GitHub" . GitHub . Consultado el 2 de mayo de 2015 .
  5. ^ "Archivos de la lista de correo de Caml> Mensaje de Xavier Leroy" . Consultado el 2 de mayo de 2015 .
  6. ^ https://caml.inria.fr/pub/docs/manual-ocaml/comp.html
  7. ^ oleg-at-okmij.org. "BER MetaOCaml" . okmij.org .
  8. ^ "Messenger.com ahora 50% convertido a Razón · Razón" . razonml.github.io . Consultado el 27 de febrero de 2018 .
  9. ^ "Flujo: un verificador de tipo estático para JavaScript" . Flujo .
  10. ^ "Inferir analizador estático" . Inferir .
  11. ^ "GitHub - facebook / pyre-check: verificación de tipo de rendimiento para python" . 9 de febrero de 2019 - a través de GitHub.
  12. ^ "Especificación de WebAssembly, intérprete de referencia y suite de pruebas .: WebAssembly / spec" . 10 de febrero de 2019 - a través de GitHub.
  13. ^ "Empresas que utilizan OCaml" . OCaml.org . Consultado el 17 de agosto de 2014 .
  14. ^ "BuckleScript: ¡Ha llegado la versión 1.0! | Tech en Bloomberg" . Tecnología en Bloomberg . 8 de septiembre de 2016 . Consultado el 21 de mayo de 2017 .
  15. ^ Yaron Minsky (1 de noviembre de 2011). "OCaml para las masas" . Consultado el 2 de mayo de 2015 .
  16. ^ https://ocaml.org/learn/companies.html

Enlaces externos [ editar ]

  • Página web oficial
  • Manual de OCaml
  • Administrador de paquetes OCaml
  • OCaml del mundo real