Caml | ||
---|---|---|
Desarrollador(es) | ||
Gérard Huet, Guy Cousineau, Ascánder Suárez, Pierre Weis, Michel Mauny (Caml pesado), Xavier Leroy (Caml Light, OCaml) http://caml.inria.fr | ||
Información general | ||
Paradigma | funcional, imperativa, orientada a objetos en OCaml | |
Apareció en | 26 de julio de 2012 | |
Diseñado por | Gérard Huet, Xavier Leroy | |
Última versión estable | 4.02.3 (27 de julio de 2015) | |
Sistema de tipos | fuerte, estático | |
Implementaciones | OCaml, Caml Light | |
Influido por | ML | |
Ha influido a | F# | |
Sistema operativo | Sistemas operativos basados en Unix (Linux, MacOSx) y Windows | |
Licencia | GNU | |
Caml (Originalmente un acrónimo para Categorical Abstract Machine Language, en español Lenguaje Máquina Abstracto Categórico) es un dialecto de la familia del lenguaje ML, desarrollado en INRIA y anteriormente en la Escuela Normal Superior de París.
Como muchos descendientes de ML, Caml es un lenguaje de tipado estático, evaluación estricta, y utiliza administración de memoria automática.
La primera implementación de Caml en Lisp fue apodada "CAML pesado" debido a los requisitos de memoria y CPU relativos a su sucesor "Caml Light", aquello fue implementado en C por Xavier Leroy y Damien Doligez. Además de una reescritura completa, "CAML Special Light" añadió un potente sistema de módulos al núcleo del lenguaje.
Actualmente, la implementación principal de Caml es OCaml, el cual añade muchas características nuevas al lenguaje, entre ellas una capa de objeto.
Lo siguiente, # representa el prompt de OCaml.
print_endline "Hello World!";;
Muchas funciones matemáticas, como el factorial, son representadas más naturalmente en una forma puramente funcional. La siguiente función recursiva, puramente funcional implementa la operación factorial en Caml:
let rec fact n = if n=0 then 1 else n * fact(n - 1);;
La función puede escribirse equivalentemente utilizando patrones de emparejamiento:
let rec fact = function
| 0 → 1
| n → n * fact(n - 1);;
Esta última forma es la definición matemática de factorial como una relación de recurrencia.
Note que el compilador infirió el tipo de esta función para ser int int → int
, significa que esta función mapea enteros a enteros. Por ejemplo, 12! Es:
# fact 12;;
- : int = 479001600
Desde que OCaml es un lenguaje de programación funcional, es fácil crear y repasar funciones en programas de OCaml. Esta capacidad tiene un número enorme de aplicaciones. Calcular la derivada numérica de una función es una de ellas. La función d
en Caml computa la derivada numérica de una función dada f en un punto dado x
:
let d delta f x =
(f (x +. delta) -. f (x -. delta)) /. (2. *. delta);;
Esta función requiere un valor infinitesimal delta
. Una buena elección para delta es la raíz cúbica del épsilon de la máquina.[cita requerida]
El tipo de la función d
indica que ésta mapea un tipo de dato flotante a otra función del mismo tipo (float → float) → float → float
. Esto nos permite aplicar argumentos parcialmente. Este estilo funcional es conocido como currificación. En este caso, es útil al aplicar parcialmente el primer argumento delta
a d, para obtener una función más especializada:
# let d = d (sqrt epsilon_float);;
val d : (float → float) → float → float = <fun>
Note que el tipo inferido indica que la sustitución d espera una función del tipo flotante float float → float
como primer argumento. Podemos computar una aproximación numérica a la derivada de la función en el punto con:
# d (fun x → x *. x *. x -. x -. 1.) 3.;;
- : float = 26.
La respuesta correcta es:
La función d
se denomina "función de alto orden" ya que acepta otra función (f) como argumento.
Los conceptos de funciones currificadas y de alto orden son útiles evidentemente en programas matemáticos. De hecho, estos conceptos son igualmente aplicables a otras formas de programación y pueden emplearse en código de factor mucho más agresivamente, resultando eprogramas más cortos y con menos errores.
La transformada Wavelet de Haar de una lista de números enteros de potencia en base dos puede ser implementada muy sucintamente en Caml y es un ejemplo excelente del uso de la concordancia de patrones sobre listas, tomando pares de elementos (h1
y h2
) del frente y almacenando sus sumas y diferencias en las listas s
y d
, respectivamente:
# let haar l =
let rec aux l s d =
match l, s, d with
[s], [], d → s :: d
| [], s, d → aux s [] d
| h1 :: h2 :: t, s, d → aux t (h1 + h2 :: s) (h1 - h2 :: d)
| _ → invalid_arg "haar"
in aux l [] [];;
val haar : int list → int list = <fun>
Por ejemplo:
# haar [1; 2; 3; 4; -4; -3; -2; -1];;
- : int list = [0; 20; 4; 4; -1; -1; -1; -1]
El patrón de emparejamiento permite transformaciones complicadas para ser representadas claramente y sucintamente (brevemente). Además, el compilador de OCaml realiza concordancia de patrones en un código muy eficaz, el tiempo en el que los programas arrojan resultados es más corto y más rápido que el código equivalente escrito con una estructura "switch-case" (Cardelli 1984, p. 210.).