Translate

domingo, 30 de diciembre de 2012

Estructuras de control de programa (Primera parte)



Condicionales


if


Es similar que en otros lenguajes: (if (condición) (entonces) (otro))

Si la condicion es verdadera se evaluara la expresión "entonces", si la condicion es falsa, se evaluará la expresión "otro".
En lisp el valor destinado para falso es NIL, que también significa lista vacia; el valor logico para verdadero es T. Veamos algunas funciones de comparación:

> (set 'x 4)
4

> (= x 4)     ; ¿x es igual a 4?
T

> (/= x 4)    ; ¿x no es igual a 4?
NIL

> (< x 5)    ; ¿x es menor que 5?
T

Vamos a los bifes con if:

> (set 'temperatura 28)
28

> (if (< temperatura 30) (set 'clima "templado") (set 'clima "caluroso"))
"templado"

When


Es similar a if, solo que no contempla el hecho de ejecutar alguna acción en el caso de la condición sea falsa, veamos:

(when (condicion) (entonces))

Cuando la condición es verdadera evalua la expresión entonces.

> (set 'nombre "maria")
"maria"

> (when (EQUAL nombre "maria") (princ "te amo, vida"))
"te amo vida"

Cond


Es inapropiado aca usar sentencias if anidadas, para evitar esto se usa cond, que evaluará cierta expresión segun la condicion sea verdadera. Es parecido y cumple la misma funcion que case o select en otros lenguajes.
Ejemplo:

(defun hacer-algo (temperatura)
       (cond ((< temperatura 10) "a mirar tele")
             ((< temperatura 30) "juguemos al futbol")
             ((< temperatura 40) "a tomar helado con mi Victoria")
             ((>= temperatura 40) "¡Vamos a la playa, Victoria!")))


> (hacer-algo 15)
"juguemos al futbol"

> (hacer-algo 36)
"a tomar helado con mi Victoria"


Case


Si se quiere tomar una decisión basada en la comparación de una variable frente a un conjunto conocido de valores constantes, case es con frecuencia más conciso que cond. Ojo, la variable no puede usarse para comparar cadenas de caracteres:

(defun elegir-color (color)
         (case color
               (:rojo "rosa")
               (:azul "tulipan")
               (:verde "malvon")
               (:lila "azucena")
               (:amarillo "margarita")
               (otherwise "¡Elija otro color!..."))) ; otro caso


> (elegir-color :lila)
"azucena"


Otro ejemplo:

(defun elegir-valor (valor)
         (case valor
               (0 "cero")
               (3 "tres")
               (9 "nueve")
               (7 "siete")
           (otherwise "¡Elija otro valor!...")))

> (elegir-valor 2)
"¡Elija otro valor!..."

En la segunda parte veremos las expresiones iterativas. Saludos :-P y felices fiestas!!!

viernes, 2 de noviembre de 2012

Crear Interfaces Gráficas en Lisp con LTK (cuarta parte)

Responder a Eventos

Para responder a eventos como ratón o teclado, etc. se puede usar bind, la sintaxis del comando es asi:

> (bind nombre-control "<nombre-evento>" (función))
Nota: En LTK los controles son llamados "widgets"

Los nombres de los eventos van encerrados siempre entre dobles comillas "" y los caracteres < y >. Por ejemplo, para cambiar de color una etiqueta cada vez que se entra con el puntero del ratón:

> (bind etiqueta "<Enter>" (lambda(x) (configure etiqueta :foreground "green")))

Si queremos que se produzca una acción, luego de haber presionado el botón izquierdo del ratón:

> (bind boton "<Button-1>" (lambda(x) (do-msg "te amo Maria")))

Que nos muestra un bonito mensaje, al presionar un botón
El siguiente ejemplo nos muestra algunos eventos comunes:

Para probarlo, copie el siguiente texto y guárdelo en un archivo "eventos.lisp" luego carguelo o ejecutelo con su lisp.

;;;----------------------------------------------------------------------------------------------------------------

(load "~/ltk-0.96/ltk.fas")           

(use-package :ltk)                       


(with-ltk()                           
    (let* ((entrada (make-instance 'entry :width 20))       
           (etiqueta (make-instance 'label :text "Gol de Messi"))
       (marco (make-instance 'frame))                 
       (boton (make-instance 'button :master marco :text "Aceptar"))) 
             

      (bind etiqueta "<Enter>" (lambda(x) (configure etiqueta :foreground "green")))   
      (bind etiqueta "<Leave>" (lambda(x) (configure etiqueta :foreground "red")))   
      (bind boton "<Button-1>" (lambda(x) (do-msg "te amo Maria")))              
      (bind etiqueta "<Double-Button-1>" (lambda(x) (do-msg "Doble click del ratón")))       
      (bind boton "<Button-3>" (lambda(x) (do-msg "Botón derecho del ratón")))   
      (bind boton "<Button-2>" (lambda(x) (do-msg "Botón central del ratón")))
      (bind entrada "<Key-a>" (lambda(x) (do-msg "Has presionado la tecla a")))            
      (bind entrada "<Key-t>" (lambda(x) (do-msg "Has presionado la tecla t"))) 
      (bind entrada "<Control-Key-t>" (lambda(x) (do-msg "Has presionado Ctrl + t")))
      (bind entrada "<Control-Alt-Key-m>" (lambda(x) (do-msg "Has presionado Ctrl + Alt + m")))
      (bind entrada "<Escape>" (lambda(x) (do-msg "Has presionado la tecla Escape")))

      (pack etiqueta)                       
      (pack entrada)                       
      (pack marco)                       
      (pack boton)                       
      (configure marco :borderwidth 3)               
      (configure marco :relief :raised)))           
  
;;;----------------------------------------------------------------------------------------------------------------
    



- Esto de los eventos, me da curiosidad...

La siguiente tabla muestra los eventos y sus modificadores:



Evento
Descripción
Modificadores
(los modificadores van separados entre guiones "-" )
ButtonPres, Button, B Se ha presionado uno de los botones del ratón. "<Button-1>": Se presiona el botón izquierdo del ratón
"<Button-2>" Se presiona el boto central del ratón
"<Button-3>" Se presiona el botón derecho del ratón
Double: Doble click con uno de los botones del ratón.
Ejemplo:
"<Double-Button-1>": Doble click con el botón izquierdo
Triple: Triple click con uno de los botones del ratón.
Buttonrelease Se ha dejado de presionar uno de los botones del ratón.

Configure El control ha cambiado de tamaño, posición, etc.

Destroy El control ha sido destruido

Enter El puntero del ratón ha entrado en el control

Leave El puntero del ratón ha abandonado el control

FocusIn El control ha tomado el foco.

FocusOut El control ha perdido el foco.

KeyPress, Key, K Se ha presionado una tecla. Va acompañado de la tecla que se presiona, por ejemplo:
"<Key-a>" "<Key-b>" "<Key-m>"
Los modificadores son: Control, Shift, Lock y Alt para las teclas: control, mayúsculas, bloqueo de mayúsculas y Alt, respectivamente. Ejemplos:
"<Control-Key-t>" Se ha presionado Control + t.
"<Shift-Key-b>" Se ha presionado Shift + b.
"<Control-Alt-Key-m>" Se ha presionado Control + Alt + m.
También existen unas teclas ya definidas, tales como:
"<Return>", "<Escape>", "<BackSpace>", "<Tab>", "<Up>", "<Down>", "<Left>", "<Right>", etc.
KeyRelease Se ha soltado la tecla presionada.

Motion El puntero del ratón se mueve sobre el control.

Map La ventana ha sido desplegada.

Unmap La ventana ha sido iconificada.


En este sitio hay un tutorial muy bueno sobre LTK de una universidad española:
 tutorial - capitulo 12

Saludos, comenten :-P

sábado, 8 de septiembre de 2012

Funciones de mapeo sobre listas

Si se tiene una lista, y se desea realizar operaciones o modificaciones para cada elemento de dicha lista, obteniendo otra de la misma longitud, se puede utilizar una función de mapeo. mapcar es la mas común de tales funciones. mapcar toma una función y uno o más listas, y aplica esa función a cada elemento de la lista, produciendo una nueva lista resultante.

 > (setq una-lista '(1 2 3 4 5))

UNA-LISTA

> (defun doble (n) (* n 2))

DOBLE

> (setq otra-lista (mapcar #'doble una-lista))

(2 4 6 8)

Observe el signo #' antes de la función doble. DOBLE es el nombre del símbolo, (definido previamente con defun), que contiene a la función. La notación #' permite acceder al espacio de función del símbolo DOBLE y pasarla como argumento a mapcar.





- Maestro, ¿¡se pueden pasar funciones como argumentos...!?

- Si, pequeño saltamontes, pues las funciones son tipos de datos en Lisp, sigue practicando...

Otro ejemplo:


> (setq cadenas '("argentina gano tres a uno" "Messi hizo un gol" "Paraguay concreto de penal"))

("argentina gano tres a uno" "Messi hizo un gol" "Paraguay concreto de penal")

> (defun cambia-letra (una-cadena) (substitute  #\@ #\e una-cadena))

CAMBIA-LETRA

> (cambia-letra "cielo celeste")

“ci@lo c@l@st@”

> (setq nuevas (mapcar #'cambia-letra cadenas)


("arg@ntina gano tr@s a uno" "Lio M@ssi hizo un gol d@ tiro libr@" "Paraguay concr@to d@ p@nal")
Para no tener que definir funciones a cada rato, existe la función "sin nombre", lambda que puede pasarse como argumento a mapcar, ahí mismo donde se define.
Para el primer ejemplo de la función doble, sería asi:

> (setq otra-lista (mapcar 

                                      #'(lambda (n) (* n 2)) 
                                      una-lista))
(2 4 6 7)

Para el segundo:

(setq nuevas (mapcar 
                       #'(lambda (una-cadena) (substitute #\@ #\e una-cadena)) 
                       cadenas))

("arg@ntina gano tr@s a uno" "Lio M@ssi hizo un gol d@ tiro libr@" "Paraguay concr@to d@ p@nal") 
Bien, lambda es la función sin nombre. Permite definir de manera instantánea la función que se va a pasar como argumento. Se usa de la siguiente manera:

(lambda (argumento) (cuerpo de la función))

some

Devuelve una valor booleano (T o NIL) si algún elemento de la lista verifica la función aplicada.

> (some #'(lambda (x) (> x 9)) '(1 2 3 4 4 6 78 13))
T

Solo basta que la función que se le pasa como argumento sea booleana, es decir que devuelva T o NIL. Aquí otro ejemplo, no se desespere:

> (some #'(lambda (x) (equal x 'futbol)) '(futbol basquet voley handball golf))
T

every

Esta es como la anterior, pero todos los elementos de la lista deben cumplir con la función que se le pasa de argumento.
> (every #'(lambda (x) (atom x)) '("agua" "gota" "barco" "cielo"))
T

atom pregunta si algo es un atomo o una lista. Si es un atomo tal como pueden ser un número, una cadena e incluso una variable, es decir es un solo elemento, devuelve T, si se trata de una lista devuelve NIL.

> (setf lista ‘(1 3 6 45 2))
> (every #'(lambda (x) (>= x 3)) lista)
NIL

apply

Su nombre mismo lo indica, “apply”ca la función a todos los elementos, solo que esta devuelve un solo valor, el valor acumulado.

> (apply #’+ lista)
57

> (apply #’append ‘((a b c) (1 5 9) (“Armando” “Esteban” “Quito”)))
(A B C 1 5 9 "Armando" "Esteban" "Quito")

remove-if

No modifica la lista actual, pero devuelve una lista como resultado de haber eliminado los elementos que verifican la función que se le pasó como argumento.

> (remove-if #'(lambda (x) (> x 5)) lista)
(1 3 2)

>  (remove-if #'atom '("Laurita" 5 ("Jose" valor) (4.1 19 #c(2 3)) “renegado”))
(("Jose" VALOR) (4.1 19 #C(2 3)))

Saludos. Comenten.  :-D

martes, 17 de julio de 2012

Crear Interfaces Graficas en Lisp con LTK (tercera parte)


Voy a mostrar un ejemplo de una aplicación con interfaz grafica:

cortar aqui
;----------------------------------------------------------------------------------------------------------------

(load "~/Descargas/ltk-0.96/ltk.fas")            ;cargo ltk desde la ruta donde lo guarde :)

(use-package :ltk)                        ;para usar los paquetes ltk


(with-ltk()                           
    (let* ((entrada (make-instance 'entry :width 20))        ;crea cuadro de entrada de ancho 20
           (etiqueta (make-instance 'label :text "Gol de Messi")) ;crea etiqueta
       (marco (make-instance 'frame))                  ;crea marco
       (boton (make-instance 'button :master marco :text "Aceptar"  ;crea boton dentro de marco
        :command (lambda() (do-msg "te amo Talia :-)")))))      ;al pulsar envia un mensaje


      (pack etiqueta)                     ;coloca la etiqueta dentro del form
      (pack entrada)                     ;coloca el cuadro de entrada
      (pack marco)                       ;coloca el marco
      (pack boton)                        ;coloca el boton
      (configure marco :borderwidth 3)                ;ajusta el ancho del borde del marco
      (configure marco :relief :raised)                ;ajusta el estilo del marco
        
      ))

;-------------------------------------------------------------------------------------------------------------

Se copia el texto de arriba en un archivo y se guarda como "ejemplo.lisp"
Para ejecutarlo (con clisp) se abre una terminal y se teclea:

> clisp ~/ejemplo.lisp



No debería ser muy distinto con otros sistemas Lisp. Obviamente se debe  colocar la ruta completa donde quedó guardado el archivo.
Mas adelante veremos como manejar eventos como hacer click con el mouse sobre un objeto, pasar con el raton por encima, presionar una tecla, etc.

domingo, 15 de julio de 2012

Listas (cuarta parte): Diversas funciones utiles


¿Es una Lista...?

 Para saber si un objeto es una lista o no, usamos la función Listp. Los valores devueltos pueden ser T (verdadero) o nil (falso).

 > (setq una-lista '("hola" "estoy a 200 km de casa" "vacaciones"))
("hola" "estoy a 200 km de casa" "vacaciones")

> (listp una-lista)
T

> (setq valor 38)
38

> (listp valor)
NIL

> (setq valor "grados")
"grados"

> (listp valor)
NIL

Lista vacía

La función null nos dirá si una lista esta vacía, es decir, que no tiene elementos. null devuelte T si la lista está vacía, caso contrario devuelte NIL. 

> (set 'lista '("hola" "como" "estas")
("hola" "como" "estas")

> (null lista)
NIL

> (set 'lista nil)
NIL

> (null lista)
T

Longitud de una lista


La longitud de una lista se obtiene con la función length:

> (setq una-lista '("uno" "dos" 3 "cuatro" 5.0 6e00))
("uno" "dos" 3 "cuatro" 5.0 6.0)

> (length una-lista)
6

Obtención de parte de una lista

subseq es una función común que se usa para devolver parte de una lista. Toma al menos dos argumentos, una lista y un entero que indica la posición desde donde empezar. También toma un tercer argumento optativo, un entero que indica la posición donde detenerse. Observe que la posición indicada por este tercer argumento no se incluye en el la sub-lista devuelta:

> (setq una-lista '("uno" "dos" "tres" "cuatro" "cinco"))
("uno" "dos" "tres" "cuatro" "cinco")

> (setq otra-lista (subseq una-lista 1 3))
("dos" "tres")

> (setq otra-lista (subseq una-lista 0 2))
("uno" "dos")

> (setq otra-lista (subseq una-lista 1))
("dos" "tres" "cuatro" "cinco")

Unir varias listas en una sola


Las listas se pueden unir con append:

> (setq lista-uno '(1 2 3 4 5 6))
(1 2 3 4 5 6)

> (setq lista-dos '("esto" "es" "una" "lista"))
("esto" "es" "una" "lista")

> (setq lista-tres '("Maria" "te" "amo"))
("Maria" "te" "amo")

> (setq lista-unica (append lista-uno lista-dos lista-tres))
(1 2 3 4 5 6 "esto" "es" "una" "lista" "Maria" "te" "amo")

Ordenar listas


Las listas se ordenan con sort:

> (setq lista-valores '(23 15 33 789 3 102 18))
(23 15 33 789 3 102 18)

> (sort lista-valores #'<)
(3 15 18 23 33 102 789)

> (sort lista-valores #'>)
(789 102 33 23 18 15 3)

El resto de una lista

La función rest devuelve la misma lista pero sin el primer elemento, es decir, devolverá el resto de la lista, luego de extraer el primer elemento. Su valor deberá ser almacenado debido a que rest es no destructiva:

> (set 'primos '(2 3 5 7 11 13 17 19 23))
(2 3 5 7 11 13 17 19 23)

> (set 'resto (rest primos))
(3 5 7 11 13 17 19 23)

Listas (tercera parte): Remover y Agregar elementos


Para remover elementos de una lista se usa la función remove:

> (setq una-lista '(15 33 "edad" 7/8))
(15 33 "hoy es domingo" 7/8)

 > una-lista
(15 33 "hoy es domingo" 7/8)

>  (remove 33 una-lista)
(15 "hoy es domingo" 7/8)

Se ha removido 33 de la lista. Sin embargo la función remove es no destructiva, por lo que no se ha modificado una-lista.

> una-lista
(15 33 "hoy es domingo" 7/8)


Por lo tanto deberíamos guardar la lista devuelta por la función:

> (setq una-lista (remove 33 una-lista))
(15 "hoy es domingo" 7/8)

> una-lista
(15 "hoy es domingo" 7/8)

Para agregar elementos se puede usar la función cons:

> (setq una-lista (cons "mañana es lunes..." una-lista))
("mañana es lunes..." 15 "hoy es domingo" 7/8)

> una-lista
("mañana es lunes..." 15 "hoy es domingo" 7/8)

Otra manera de agregar elementos es usando push. Una lista se puede tratar como una estructura de pila LIFO. Antes de poner cualquier valor, la lista debe tener algún elemento o estar vacía (tener el valor nil). 

Primero me aseguro de crear una lista vacía:

> (setf una-lista nil) 
NIL

> (push "hola" una-lista)
("hola")

> (push 23 una-lista)
(23 "hola")

> (push () una-lista)
(NIL 23 "hola")

> (push "te amo Maria" una-lista)
("te amo Maria" NIL 23 "hola")

> (push 8.5 una-lista)
(8.5 "te amo Maria" NIL 23 "hola")

Para sacar usamos pop:

> (pop una-lista)
8.5

Pero los valores que quitamos se perderían de no ser asignados:

> (setq hermosa (pop una-lista))
"te amo Maria"

> hermosa
"te amo Maria"

Listas (segunda parte) Acceder a los elementos de una lista


Para acceder al primer elemento se usa first:

> (setq una-lista '("uno" "dos" "tres" "cuatro" "cinco"))
("uno" "dos" "tres" "cuatro" "cinco")

> (setq cadena (first una-lista))
"uno"

Accede al primer elemento de la lista una-lista y guarda el valor devuelto en el simbolo cadena.

> cadena
"uno"

Para acceder al segundo y al tercero, second y third, respectivamente:

> (setq cadena (second una-lista))
"dos"

> (setq cadena (third una-lista))
"tres"

Para obtener cualquier elemento de una lista, se puede usar nth:

> (setq cadena (nth 4 una-lista))
"cinco"

> (setq cadena (nth 0 una-lista))
"uno"

> (setq cadena (nth 2 una-lista))
"tres"

Al primer elemento se accede con 0 al segundo con 1, y asi sucesivamente.

Para acceder al ultimo elemento de una lista se puede usar last:

> (setq cadena (last una-lista))
"cinco"




martes, 10 de julio de 2012

Crear Interfaces Gráficas en Lisp con LTK (Segunda parte)

Voy a mostrar algunos ejemplos de interfaces graficas. Son ejemplos tontos que escribí hace ya algun tiempo experimentando con LTK. Es nada mas que para mostrar las funcionalidades.

Con el archivo ltk.fas previamente cargado y estando dentro del paquete ltk, cargamos el archivo hola.lisp.

Que podes descargarlo desde aca:  hola.lisp

1. Entra al Lisp:
> clisp
>

2. Ahora carga el ltk.fas:

> (load "~/Descargas/ltk.fas")

3. Tenes que estar dentro del paquete ltk:

> (in-package :ltk)

4. Carga el archivo hola.lisp que descargaste:

> (load "~/Descargas/hola.lisp")

5. Ya está. Listo para probar los ejemplos

> (hola-1)
-----------------------------------------
> (hola-2)
-----------------------------------------
> (test)
-----------------------------------------
> (test-2)
-----------------------------------------
> (test-3)
Y asi sucesivamente, hasta test-6 inclusive.
 
Dentro del archivo de texto "hola.lisp" podes ver el codigo de los ejemplos con cualquier editor de textos. Ok, :-) 
Aquí una guía en ingles para ltk, ltk.doc.

sábado, 7 de julio de 2012

Crear Interfaces Gráficas en Lisp con LTK (primera parte)

Como este tema esta ya muy bien explicado en http://lispinspain.blogspot.com.ar/2008/09/primeros-pasos-con-ltk-parte-1.html no voy a ahondar en muchos detalles. Sin embargo voy a explicar como descargar e instalar las librerías LTK de forma sencilla, debido al hecho de que la instalacion mediante asdf-install ha quedado obsoleta en la actualidad.
Estas librerías nos permitiran generar ventanas, crear botones, y todo tipo de controles.

a. Instala tcl/tk 8.5

Si tenes alguna distribución linux, hay que instalar primero los paquetes tcl8.5 y tk8.5. Voy a mostrar la instalación en ubuntu:

Abri una terminal y logueate como administrador:

> sudo su

Instala los paquetes con apt-get, o con algun gestor de paquetes.

> apt-get install tcl8.5

> apt-get install tk8.5

Si tu sistema operativo es Windows puedes descargar e instalar la última versión de ActiveTcl desde: https://www.activestate.com/activetcl/downloads
Asegurate de tener el sistema operativo actualizado, prueba ejecutar c:\ActiveTcl\bin\wish.exe y te aparecerá una ventana vacía. Si da error debes actualizar Universal C Runtime: https://support.microsoft.com/es-ar/help/2999226/update-for-universal-c-runtime-in-windows

b. Descarga las librerias LTK

Se puede descargar desde: http://beta.quicklisp.org/archive/ltk/2011-07-30/ltk-0.96.tgz

O desde mi cuenta de box: https://www.box.com/s/e2d42ef29fd4d3c34150

c. Descomprime los archivos


d. Compilar el archivo "ltk.lisp"

Entre los archivos que descomprimiste hay uno llamado "ltk.lisp", hay que compilarlo. Ejecuta tu lisp en una terminal y manos a la obra.

> (compile-file "~/Descargas/ltk-0.96/ltk.lisp")

e. Cargar "ltk.fas"
 

Luego de haberse compilado se genera el archivo "ltk.fas". Hay que cargarlo:

> (load "~/Descargas/ltk-0.96/ltk.fas")

f. Ingresar al paquete ltk

Hay que estar en el paquete ltk para cargar los programas:

> (in-package :ltk)

g. Probar que todo funciona

Para probar que todo funciona correctamente hay unos test:

> (ltk::ltk-eyes)

Debería mostrarnos una ventana con ojos que siguen al ratón.

> (ltktest)
Nos muestra una ventana con algunos controles.

lunes, 2 de julio de 2012

Listas (primera parte) Crear una lista


Para crear una lista se puede asignar una lista a un simbolo nuevo:

> (setf mi-lista '(6 "esto es una lista" nil T))
(6 "esto es una lista" nil T)

Otra forma es usando la función list:

> (setf (lista (list 34 5 78))
(34 5 78)

> lista
(34 5 78)

Setf es la forma mas general de asignación (que yo conozca). Asigna a un símbolo el resultado de la función que le sucede a continuación o un valor de cualquier tipo. En el primer ejemplo, 6 es un entero, "esto es una lista" es una cadena de caracteres y los valores nil y T son los equivalentes lógicos en lisp para FALSO y VERDADERO respectivamente.
También podés crear una lista vacía:

> (setf una-lista nil)
NIL

> una-lista
NIL



viernes, 15 de junio de 2012

Tipos de datos en Lisp


Tipos de datos en Lisp:

En Lisp tenemos: números, cadenas de caracteres, listas, símbolos y funciones.

CADENAS DE CARACTERES
Las cadenas de caracteres van entre comillas, como en otros lenguajes:

> “esto es una cadena”
“esto es una cadena”

SIMBOLOS
Los símbolos son espacios de memoria que pueden contener valores tal como lo hacen las variables en otros lenguajes. Sin embargo, aquí un símbolo es algo mas que lo que llamamos variable en otros lenguajes, así como ellas tiene un nombre que es una cadena de caracteres, y puede tener un valor asociado que puede ser un numero, una cadena o una lista. Pero además del espacio de valor, posee otros dos espacios: un espacio de función, y un espacio de lista de propiedades o plist.


Una de las manera de asignar un valor a un símbolo es usando setq:

> (setq x “Hola”)
“Hola”
> (setq y 45)
45

El intérprete siempre evalúa lo que pongamos en el prompt. Si colocamos el símbolo, evaluará y devolverá su valor.

> x
“Hola”

> y
45

Si colocamos cualquier valor, devolverá el valor mismo.

> “Gato”
“Gato”

Si colocamos una función devolverá el resultado luego de evaluarla:

> (cuadrado 3)
9

Para desactivar la evaluación usamos la función quote y nos devolverá el símbolo mismo:

> (quote x)
X

Para simplificar el uso de quote se usa la comilla simple:

> 'x
X

> 'y
Y

LISTAS
Las listas pueden contener números, cadenas, símbolos, funciones y otras listas. Una de las maneras de hacer una lista es desactivando la evaluación:

> '(1 4 56)
(1 4 56)

Pues de lo contrario evaluará a la lista, tomándola como una función:

> (1 4 56)
*** - EVAL: 1 is not a function name; try using a symbol instead

El intérprete intenta tomar a 1 como nombre de una función y el resto serían sus argumentos. Como no se pueden usar números como nombres de función devuelve error.

Otro ejemplo:
> '(cuadrado 4)
(CUADRADO 4)

Como la evaluación está desactivada, el intérprete devuelve la lista formada por el símbolo cuadrado y el número 4. Con la evaluación activa:

> (cuadrado 4)
16

Evalúa la función cuadrado y devuelve el resultado correspondiente.

Otro ejemplo de lista y van...
> '(2.32 -7 4E-5 #C(1 -1) “esta lista es copada” (1 2 3 a) b)
(2.32 -7 “esta lista es copada” (1 2 3 A) B)


NUMEROS
Los números pueden ser enteros, decimales, de coma flotante, fracciones o complejos.

Tipos
Ejemplos
Enteros
> -3
-3
> 5
5
Decimales
> 7.8
7.8
> 3.14159265
3.14159265
Notación Científica
> 4.46E4
44600.0

> 1.65E6
1650000.0
> 7.9E-12
7.9E-12

> 8.2E32
8.2E32
Fracciones
> 2/3
2/3
> -5/8
-5/8
Complejos
El primer valor corresponde a la parte real, el segundo a la imaginaria.
> #C(2 3)
#C(2 3)


> #C(-1 5)
#C(-1 5)

Algunas Operaciones Aritméticas

Operación Aritmética
Ejemplos
Suma
> (+ 1 2)
> 3

> (+ 3.2 7)
10.2
> (+ 3/2 1/5)
17/10

> (+ #C(2 3) #C(1 -5))
#C(3 -2)
Resta
> (- 6 9)
-3
> (- #C(1 1) #C(2 3))
#C(-1 -2)
Multiplicación
> (* 3 4)
12
> (* 2 3 7)
42
División
> (/ 4 -2)
-2
> (/ 15 6)
5/2
Potencia
> (expt 2 3)
8

> (expt 7/8 5)
16807/32768
> (expt #C(4 -1) -2)
#C(15/289 8/289)
Raíz cuadrada
> (sqrt 16)
4


PD: Aquí tengo el libro de Cooper traducido al español:
Técnicas Básicas de Lisp - David Cooper.pdf 

martes, 1 de mayo de 2012

Llamar y Definir funciones

Antes de comenzar debemos saber como entrar y salir de nuestro intérprete. Para iniciar abrimos una terminal, consola o línea de comandos (o símbolo del sistema). Escribimos el nombre de nuestro programa, por ejemplo para clisp:

> clisp

Iniciará el programa del intérprete lisp, con alguna información según el caso.
Para finalizar y devolver el control de la consola al sistema operativo, escribimos:

> (quit)

Llamadas a Funciones

Las funciones son de fundamental importancia aquí. Las llamadas a funciones tienen una estructura determinada:

(nombre argumentos)

Todas las funciones irán entre paréntesis. Las funciones pueden tener uno, varios o ningún argumento. Aquí muestro algunos ejemplos de llamadas a funciones desde el intérprete:

> (+ 2 3)
5

> (write-string "holaaa")
holaaa
"holaaa"

> (* 4 7)
28

> (* 3 4 2)
24

Para asignar valores a variables, usamos la función setf:

> (setf x 45)
45

Colocando el nombre, el interprete evalua y devuelve el valor:
> x
45

Para crear listas de objetos diversos, podemos usar la función list (veremos mas adelante sobre los distintos tipos de datos en lisp):

> (list 34 "cadena de caracteres" 3.14 2/3 (+ 6 7))
(34 "cadena de caracteres" 3.14 2/3 13)

> (setf x 23)
23
> (list 67 5.32 3/8 "octubre" (+ 2 3) x)
(67 5.32 3/8 "octubre" 5 23)

Definir funciones

En Lisp, la forma mas fácil de definir funciones es usando la macro defun. Veamos un ejemplo de creación de una función en el intérprete:

> (defun hola () (write-string "Hola mundo!"))
HOLA

Primero va el nombre de la función, en este caso hola, luego los argumentos, en este caso la función no posee ningún argumento, y por ultimo va el cuerpo de la función.
Otro ejemplo muy conocido para mostrar las definiciones de función en lisp:

> (defun cuadrado (n) (* n n))
CUADRADO

Probamos la función:

> (cuadrado 9)
81

Otro mas:

> (cuadrado 4)
16

Otro ejemplo de definición de funciones:

> (defun cubo (n) (* n n n))
CUBO

Genial! probamos la función:

> (cubo 5)
125

> (cubo 3)
27

Una vez que salimos del intérprete, las definiciones de función creadas se perderán.
¿Cómo guardamos estos datos?
Abrimos un editor de textos cualquiera o emacs con slime y escribimos en él:

(defun hola ()
   (write-string "Hola, mundo!"))

(defun cuadrado (n)
   (* n n))

(defun cubo (n)
   (* n n n))

Guardamos el archivo como "primero.lisp" o lo que sea .lisp.
Si entramos en el intérprete nuevamente, las funciones creadas no estarán cargadas en el sistema. Para cargarlas usamos la función load:

> (load "ruta.../primero.lisp")

Y las funciones creadas estarán disponibles en el intérprete. También podemos compilar el archivo .lisp antes de cargarlo, con lo cual se creará un archivo .fas o .fasl según el tipo de interprete que estemos usando. Esto se hace así:

> (compile-file "ruta.../primero.lisp")

De esta manera crea el archivo "primero.fas" en un lenguaje mas cercano a la máquina. El código se ejecutará mas rápido, esto no se notará en programas pequeños pero si en programas mas extensos. Para cargarlo usamos la función load:

> (load (ruta.../primero.fas")

PD: aquí dejo una guía rápida que encontré en algún momento navegando, hace rato ya:


domingo, 29 de abril de 2012

Entorno de Desarrollo Lisp

Bien, antes de comenzar necesitamos tener un entorno de desarrollo para lisp. Para ello debemos tener instalado un interprete de lenguaje Common Lisp. Hay varios: clisp, gclisp, allegro, LispWorks, Jabberwocky, Garnet, etc. Los archivos de programa lisp, son simples archivos de texto, razón por la cual necesitamos un editor de textos para guardar los archivos lisp (a los que le pondremos la extensión .lisp "o .lsp"), puede ser cualquiera, aunque uno muy bueno es el Emacs, que con Slime instalado genera un entorno de desarrollo lisp en modo texto muy amigable, con dentado, control de paréntesis, colores y demas cosas.
En ubuntu es muy fácil instalar todo, tanto el clisp como el Emacs con slime se encuentra en los repositorios. 


Para instalarlo en ubuntu:

sudo apt-get install emacs23

sudo apt-get install slime

 Para Windows hay que descargar el instalador de clisp desde:

En este blog hay una guía para descargar el emacs + slime para windows:


Saludos y éxitos!

PD: Aca tengo la traduccion del libro de Cooper:
Técnicas Básicas de Lisp