Tutorial de OCaml: Capitulo 1.

Escrito el 12 Julio, 2001 – 13:01 | por storm | 6.636 lecturas

Esta es nuestra primera entrega del tutorial exclusivo de Ocaml de Maldita Internet, un lenguaje que combina programacion funcional, procedural, objetos y mucho mas. En la primera entrega lo basico del lenguaje, los tipos basicos, algunas funciones como para empezar a jugar y el link a las distribuciones.

Introduccion a Ocaml

Introduccion e Historia: Ocaml es un derivado de ML, ML es un lenguaje de programacion funcional creado por Robert Milner en 1975, el lenguaje ML en si fue creado como un prototipo y pronto de el se desprendieron varios lenguajes de programacion entre los que se destacaron el Haskell y el Caml. Caml sufrio varias modificaciones a lo largo de su historia, en 1985 se crearon Caml-Light y OCaml, las dos versiones mas difundidas hoy en dia, estandarizando el lenguaje y llevandolo a su forma definitiva. Ocaml es un lenguaje extremadamente moderno, la ultima modificacion al core del lenguaje fue realizada en el 2000 con el agregado, por ejemplo, de tipos variantes anonimos

Con respecto al lenguaje en si Ocaml es, por ser un derivado de ML, un lenguaje funcional; lo cual quiere decir que es posible realizar programas completos y complejos sin necesidad de usar programacion procedural, ciclos o asignacion de variables, todo puede hacerse mediante funciones. Por otro lado Ocaml es tambien un lenguaje procedural ya que permite definir variables, usar ciclos y hacer todo lo habitual en lenguajes como C o Pascal. Ocaml es un lenguaje de tipo “estricto” lo cual implica que el compilador es extremadamente quisquilloso con respecto a los tipos de datos y no permite compilar programas en los cuales existan inconsistencias en los tipos. Caml es tambien un lenguaje orientado a objetos incorporando clases, herencia y polimorfismo. Por ultimo Ocaml es un lenguaje “seguro”, lo cual implica que una vez compilado un programa si el mismo no entra en loop entonces se garantiza que el programa terminara con algun tipo
de resultado, no existen errores de punteros, de mal manejo de memoria, de asignaciones invalidas, de vectores fuera
de rango, etc. El compilador esta orientado especificamente pues, a hacer que la compilacion sea muy exigente en cuanto
a errores lo cual alarga el tiempo de desarrollo y acorta sensiblemente el tiempo de debugging. En este aspecto Ocaml
es similar en cierta forma al ADA.

Ocaml super-basico:Vamos a comenzar esta introduccion con una aproximacion basica al lenguaje. En primer lugar un programa en Ocaml puede o bien compilarse o bien probarse en el modo interactivo, en modo interactivo Ocaml nos muestra un prompt donde podemos ingresar expresiones, funciones, etc y hacer pruebas. Todos nuestros ejemplos estaran basados en principio en el modo interactivo, al cual se accede corriendo el ejecutable de la version windows o bien corriendo “./ocaml” en la version para Unix. En Ocaml las sentencias terminan con “;;” (doble punto y coma) por lo que nuestro primer programa sera el clasico:

print_string("Hola mundo");;

Como podemos ver el resultado es que se muestra “Hola mundo” como salida del programa.

Tipos de datos:en Ocaml se utilizan los tipos de datos basicos de cualquier lenguaje: strings, chars, integers, floats y boolean. Tambien existe el tipo “unit” similar al “void” de C que es un tipo que no tiene tipo. Ocaml es, como dijimos, muy restrictivo y cualquier tipo de operacion que combine tipos incorrectamente sera penalizada. Por ejemplo las operaciones aritmeticas habituales que son +,-,*,/ son reemplazadas por +.,-.,*.y /. si se quieren usar floats.

Continuando con lo basico:El siguiente programa muestra como asignar una variable y como crear una funcion, dos tareas basicas.

let x = 5;;let cuadrado x = x * x;;

En el ejemplo asignamos a la variable “x” el valor “5” (entero) y definimos la funcion cuadrado que eleva un numero al cuadrado, al crear la funcion vamos a ver algo de la forma: val cuadrado -> = que nos informa que cuadrado es una funcion que toma un entero y devuelve otro. Si tratamos de usarla con un flotante tendremos un error de inconsistencia de tipos. La construccion “let” tiene aplicaciones mas que curiosas que no vamos a comentar ahora para no atemorizar a los lectores, simplemente les prometemos cosas interesantes para mas adelante.

Las funciones pueden definirse en forma recursiva usando la palabra reservada “rec”, por ejemplo la siguiente funcion calcula numeros de Fibonacci

let rec fib n =  if n < 2 then 1    else fib(n-1) + fib(n-2);;

Si no usamos la palabra rec no podemos llamar a fib dentro de fib

En Ocaml las funciones pueden pasarse como parametros a otras funciones e incluso una funcion puede devolver como resultado una funcion, introducimos de esta forma el tipo de datos “funcion” que es en Ocaml simplemente un tipo de dato mas. Por ejemplo podemos definir la composicion de funciones de la forma:

  let compose f g = fun x -> f (g x);;

Aqui definimos que la composicion de f y g diciendo que es una funcion de x,donde f y g reciben un valor x y se devuelve el resultado de aplicarle
f a g(x). Podemos probar haciendo:

  let compose f g = fun x -> f (g x);;  let cuad = x * x;;  let incr = x + 1;;  let ci = compose cuad incr;;  ci 8;;

Que como resultado devuelve 81, ya que ci es una funcion que compone el incremento y la potencia, lo que hace ci al recibir 8 es cuad(incr 8) o sea (8+1) * (8+1). La habilidad de manipular funciones de Ocaml es una de las caracteristicas mas poderosas del lenguaje.

Mas sobre let:La construccion let que permite asociar valores a variables o cuerpos a nombres de funcion tiene la caracteristica de ser anidable, por ejemplo:

  let x = 9;;  let y = 8;;  let x = 2 in    let y = 1 in       x + y;;  x + y;;

Aqui el primer x+y devuelve 3 pero el segundo devuelve 17, lo que hicimos fue crear instancias especiales de x e y para la ejecucion de la suma, estas “nuevas” variables x e y ocultan a las anteriores pero solo valen dentro del “scope”,alcance en el que fueron definidas.

Pattern matching:Otra caracteristica importante de Ocaml es el mecanismo de “pattern matching” que permite definir funciones haciendo distintas cosas segun el valor que reciban, es el equivalente a un “case o switch” en un lenguaje como “C” con la salvedad de que en un lenguaje funcional esto es elegante mientras que en los lenguajes procedurales es bastante desprolijo y en un lenguaje orientado a objetos directamente esta mal. Aqui es donde Ocaml se parece mucho a Lisp y su tradicional funcion “cond”. Veamos un ejemplo de como usar pattern matching para la funcion que calcula los numeros de Fibonacci.

  let rec fib n =    match n with    0 -> 1    |1 -> 1    |j -> fib(j-1) + fib(j-2);;

Lo cual puede leerse como: si n matchea con 0 entonces devuelvo 1, si n matchea con 1 entonces devuelvo 1, si n matchea con j (o sea con cualquier cosa que no sea 0 o 1 y que asignamos a j) entonces devuelvo fib(j-1)+fib(j-2). Como podemos ver la sintaxis de “match” es sencilla.

Cuando el body es una expresion match es valida la siguiente sintaxis alternativa:

  let rec fib n = function     0 -> 1     |1 -> 1     |j -> fib(j-1) + fib(j-2);;

En el siguiente ejemplo construimos una funcion que dice si un numero es par

  let es_par x =  match x mod 2 with     0 -> true    |1 -> false;;

La idea es simple, si x mod 2 es 0 entonces es verdadero que el numero es par y sino es falso. Curiosamente este
ejemplo nos dara un “warning” del compilador que sirve para introducir varios temas: en primer lugar es fundamental
no ignorar los warnings, siempre hay que corregirlos. En este caso el warning es que la funcion recibe un entero y
no esta contemplado el caso en el cual el numero es negativo. Para ello podemos agregar una opcion mas al pattern que
diga que si se recibe cualquier otra cosa se devuelva un error.

  let es_par x =  match x mod 2 with     0 -> true    |1 -> false    |_ -> raise(parametro_invalido "es_par");;

Aqui vemos como el uso de “_” underscore permite indicar un pattern que matchea cualquier otra cosa no matcheada hasta ahora (un default), y ademas vemos como generar un error levantando una excepcion, Ocaml al igual que Java maneja todos los errores en tiempo de ejecucion mediante el uso de excepciones, tema que veremos mas adelante

Links utiles:En el siguiente link pueden obtener las versiones para Windows o Linux de Ocaml para empezar a aprender el lenguaje.

Distribuciones

A continuacion:En nuestra proxima entrega analizaremos tipos de datos mas avanzados de Ocaml como las tuplas, listas y el concepto de polimorfismo de Ocaml. Por el momento como ejercicio es una buena idea definir funciones en forma recursiva y usando patterns y probar distintas cosas como par ir acostumbrandose al ambiente. Buena suerte.

You must be logged in to post a comment.

Buscar: