Skip to content
jcarlosgarcia edited this page Jul 22, 2012 · 9 revisions

#Empezando

Bueno ya tenemos instalado clojure en nuestro sistema. Vamos a abrir la consola y a empezar:

clj Clojure 1.3.0

User=> Ya podemos empezar a programar.

Cada comando que ejecutemos en la consola nos pondrá User=> por lo que para los siguientes ejemplos lo ignoraremos.

Aritmética

Iniciemos con simple aritmética.

(+ 2 2)
4
(* 3 4)
12
(quot 5 2) 
2
(/ 5 2) 
5/2
(/ 5.0 2) 
2.5
(- 50 25) 
25

En Clojure la división con el símbolo / se expresa como fracción (5/2) si los números son enteros, si uno de los números es con punto decimal, el resultado será con punto decimal. quot se usa para división entera.

Como podemos ver Clojure tiene construcciones para fracciones y las operaciones son en forma prefija. En caso de querer hacer múltiples operaciones, se evalúa primero el resultado entre paréntesis.

(+ (* 5 3) (- 2 20))
-3
(/ (* 3 3) (* 7 6)) 
3/14

En el primer caso (+ (* 5 3) (- 2 20) ) => (+ 15 -18)=>-3

En el segundo (/ (* 3 3) (* 7 6) ) => (/ 9 42) => 3/14

Booleanos

Clojure usa true (verdadero) y false (falso) como valores booleanos y and (y), or (o), not (no) como operadores lógicos.

(and true true)
true
(or true false)
true
(not true)
false
(not (and true false))
true
(or (and true false) (and true true))
true

Aunque los operadores lógicos and y or también aceptan más de dos parámetros en caso de and sólo es verdadero si todos los parámetros son verdaderos y en caso de or si al menos un parámetro es verdadero.

(and true true true)
true
(and false true true)
false
(or false false true)
true

Variables

Definiciones locales: Si necesitamos declarar una variable podemos usar def.

(def dos (2))
dos
2
(* 10 dos)
20

Funciones

Los lenguajes funcionales están basados principalmente en funciones parecidas a las funciones matemáticas. Entre corchetes se indican los argumentos.

Se crea una función con nombre:

(fn duplicar [x] (* 2 x))

;;Una función anónima (Sin nombre)

(fn[x] (* 2 x))

;;Una forma más corta de escribir una función anónima.
;;En este caso el argumento es % en caso de que sólo se pase un argumento a la función.
;;En caso de 2 o más toman la forma de %1, %2 ... %n, para n argumentos.

#(* %)

;;Aunque estas funciones no están disponibles en el scope, tenemos que definirlas como las variables

(def duplicar (fn duplica[x] (* x x) ))


;; Clojure ya proporciona una forma de declarar funciones, más su documentacion.

(defn duplicar[x]

"Duplica un numero"

(* 2 x))

Pitagoras a b = aa + bb

En Clojure:

(defn pitagoras [a b]

( + (* a a) (* b b) ) )

En clojure por norma las funciones que devuelven booleanos se nombran con el signo de ? al final del nombre.

(defn triangulo-rectangulo? [a b c]
(= (pitagoras a b) c))

Podemos hacer funciones mucho más complejas uniendo otras. En los lenguajes de programación imperativos tenemos estructuras de control (if, swich) e iteración (while, for). Los lenguajes funcionales prefieren la combinación de funciones en vez del orden secuencial de la programación estructurada.

La función condicional en Clojure

(if condición -si se cumple- -si no se cumple-)

(if (= 2 2) "Estás bien" "Estás mal")

"Estás bien"

(defn es-par[n]
 (if (= (mod n 2) 0) "Es par" "No es par") )

(es-par 3)

"No es par"

Si tenemos dos jugadores a y b cada uno con un puntaje, el que tiene el mayor puntaje gana y si tienen el mismo empatan. Vamos a ver cómo hacer esta función.

(defn resultado[ a puntaje-a b puntaje-b]
      (if (> puntaje-a puntaje-b) (str "Gana" " " a)
       (if(< puntaje-a puntaje b) (str "Gana" " " b) 
             (str "Empate entre" " " a " " "y" " " b) ))

La funcion str concatena cadenas.

El uso de if parece algo engorroso. También tenemos la función cond.

(cond -Condición- resultado -Condición-2- resultado-2 ...)

cond toma pares de condición, resultado y devuelve el resultado de la primera condición que devuelva verdadero.

Reescribiendo nuestro ejemplo tendríamos

(defn resultado[ a puntaje-a b puntaje-b]
 (cond (> puntaje-a puntaje-b) (str "Gana" " " a)
       (< puntaje-a puntaje b) (str "Gana" " " b)
:else (str "Empate entre" " " a " " "y" " " b) )