Sei sulla pagina 1di 30

INTRODUCCIN AL

LENGUAGE COMMON
LISP

IIIA 2005-2006

Introduction
IIIA

TAPIA 2005-2006 2
Introduccin
IIIA

Bibliografia bsica:

- Peter Norvig: Artificial Intelligence


Programming: Case Studies in Common Lisp
- Steele Jr., Guy L : CommonLISP the
language second edition. Digital Press
TAPIA Site (Paul Graham)
Implementaciones de CommonLisp:
MCL
Harlequin
Allegro
LispWorks (+ CAPI)

www.lispworks.com
www.franz.com CLOS (Object System)
www.digitool.com CLIM (Interface Manager)

TAPIA 2005-2006 3

Introduccin: LIST Processing


IIIA

Cuando se inicia la ejecucin de LISP siempre aparece un prompt como >


Despus se puede teclear y obtener resultados
> (+ 2 2)
4
Las expresiones aritmticas siguen la notacin prefija. Los resultados
de los clculos son impresos por el evaluador. La notacin prfija es ms
compacta que la infija
> (+ 1 2 3 4 5 6 7 8 9 10) 55
> (- (+ 9000 900 90 9) (+ 5000 500 50 5)) 4444
Las expresiones se pueden anidar. La regla de evaluacin es mucho ms
simple que la usual en matemticas u otros lenguajes de programacin.
Primero se evaluan los argumentos y posteriormente se aplica la funcin
sobre los resultados de la evaluacin.
Una diferencia inicial para programadores de otros lenguajes de
programacin es que no hay diferencia entre expresin y sentencia. en C
2 + 2 tiene un valor, en cambio x = 2 + 2 no. En LISP toda expresin,
tenga efecto o no, devuelve un valor.

TAPIA 2005-2006 4
Symbolic Computation
IIIA

Las reglas lxicas son mucho ms simples en LISP. Solo hay parntesis,
comillas (sencilla, doble y backquote) espacios y comas. El punto y coma
no separa expresiones (no es necesario debido a los parntesis) sino que
inicia comentarios.

LISP permite la manipulacin de smbolos, y la construccin de


estructuras de datos complejos a partir de ellos.
> (append '(Carlos Antonio) '(Carmen Rosa))
(CARLOS ANTONIO CARMEN ROSA)
La parte extraa es el ('), que sirve para bloquear la evaluacin de una
expresin y devolverla literalmente.
> '(Carlos Antonio) (CARLOS ANTONIO)
> 'A A > (quote A) A
> '2 2
>22

TAPIA 2005-2006 5

Symbolic Computation
IIIA

> '(+ 2 2) (+ 2 2)
> (+ 2 2) 4
> A Error: A is not a bound variable
> (Carlos 'Antonio) Error: Carlos is not a function
Los clculos simblicos y numricos se pueden mezclar.
> (+ 2 (length '(a b c d))) 6

LISP no otorga ninguna semntica a los smbolos que manipula.


CommonLISP contiene un conjunto de funciones predefinidas que es
necesario conocer. Como +, append, length.

Los smbolos en CommonLISP no son casesensitive.


Muchos signos de puntuacin son autorizados para formar parte de los
smbolos: '?!$/<=>'

TAPIA 2005-2006 6
Variables
IIIA

Los smbolos se utilizan para dar nombre a las variables. Una variable
puede tomar como valor cualquier objeto LISP.

> (setf p '(esto es una asignacion))


> p (esto es una asignacion)
> (setf x 10)
> (+ x x) 20
> (+ x (length p)) 14
> (setf a 3 b 5)

Los smbolos se utilizan tambin para dar nombre a las funciones. Un


mismo smbolo puede ser a la vez nombre de una variable y nombre de
una funcin.

TAPIA 2005-2006 7

Special forms
IIIA

En los ejemplos anteriores setf viola la regla de evaluacin. No evalua sus


argumentos y luego aplica la funcin al resultado de esta evaluacin. Setf
no es una funcin. Se trata de uno de los componentes de la sintaxis
bsica de LISP. A las expresiones sintcticas de LISP se las conoce
como Special forms. Por ejemplo,

(setf x (+ 1 2) )

A veces se denomina Special form a los smbolos como setf y a veces a


las expresiones encabezadas por estos smbolos, lo cual puede crear una
cierta confusin.

A lo largo de esta introduccin veremos unos cuantas special forms de


CommonLisp.

TAPIA 2005-2006 8
Listas
IIIA

Dado que las listas son esenciales en LISP, veremos unas cuantas funciones de
procesado de listas.
> p (esto es una asignacion)
> (first p) esto ; equivalente a (car p)
> (second p) es ; equivalente a (cadr p)
> (third p) una ; equivalente a (caddr p), etc.
> (fifth p) nil
> (length p) 4
Algunos detalles sobre listas. rest (o cdr) devuelve la lista resultante de
eliminar el primer elemento de la lista argumento. NIL y () son completamente
equivalentes. NIL tambin se utiliza para representar el valor falso.
Las listas pueden contener sublistas como elementos.
> (setf x '((una sublista) 2 (tercero) ((4)) 5)) ((una sublista) 2 (tercero) ((4)) 5))
> (first x) (una sublista) > (second x) 2
> (third x) (tercero) > (fourth x) ((4))
> (second (first x)) sublista

TAPIA 2005-2006 9

Listas
IIIA

Aparte de acceder a los elementos de las listas, tambin podemos


construir listas.
> p (esto es una asignacin)
> (cons 'porque p) (porque esto es una asignacin)
> (cons (first p) (rest p)) (esto es una asignacin)
> (setf ciudad (list 'Paris 'Roma)) (paris roma)
> (list p 'de (list ciudad) 'tachin) ((esto es una asignacion) de ((paris
roma)) tachin)
> (cons 'Paris (cons 'Roma ())) (paris roma)
> (append p ciudad) (esto es una asignacion paris roma)

Cons viene de Construct. Estas funciones crean nuevas listas sin


destruir las listas preexistentes.
> (last p) (asignacion)
> (first (last p)) asignacion

TAPIA 2005-2006 10
Bases listas
IIIA

o Para las listas solo es necesario


o Lectura
o first
o Rest
o Escritura
o cons
o nil

TAPIA 2005-2006 11

Funciones
IIIA

La forma especial defun viene de "define function". Se utiliza para definir


funciones.
(defun last-name (name)
"Selecciona el apellido de un nombre representado como una lista. (en
formato sajn)"
(first (last name)))
La funcin recibe un nombre last-name, tiene una lista de parmetros que
contiene un nico parmetro (name). Tambin tiene una cadena de documentacin
que dice que es lo que la funcin hace. El cuerpo de la funcin es (first (last
name)). En general
(defun function-name (parameter ...)
"Documentation string"
function-body ...)
Una vez definida, la funcin se puede utilizar como cualquier otra funcin LISP.
> (last-name '(John Q Smith)) SMITH
> (last-name '(Antonio De las Cruces Revueltas)) REVUELTAS
> (last-name '(Aristoteles)) Aristoteles

TAPIA 2005-2006 12
Funciones
IIIA

Podemos definir la funcin first-name


(defun first-name (name)
"Selecciona el nombre de pila de name representado como lista"
(first name))
Las razones de hacerlo son: legibilidad y mantenimiento.

> (setf nombres '((Sir Antonio Lopez) (Seor Pepe Galvez)


(Don Pepe Cuena) (Mr Carlos Sierra)))
((Antonio Lopez) (Pepe Galvez) (Pepe Cuena) (Carlos Sierra))

> (mapcar #'last-name nombres)


(LOPEZ GALVEZ CUENA SIERRA)

TAPIA 2005-2006 13

Utilizando funciones
IIIA

La notacin #' relaciona el nombre de la funcin con la funcin misma. En


este sentido es similar con la notacin 'x. La llamada a mapcar anterior
es equivalente a
(list (last-name (first nombres))
(last-name (second nombres))
...)
Mapcar viene de "to map" una funcin sobre los sucesivos car delos
argumentos. Car viene de "contents of the address register" y cdr de
"contents of the decrement register" las instrucciones utilizadas en la
primera implementacin de LISP sobre el IBM 704.
> (mapcar #'- '(1 2 3 4)) (-1 -2 -3 -4)
> (mapcar #'+ '(1 2 3 4) '(10 20 30 40)) (11 22 33 44)
Podemos eliminar los ttulos honorficos de los nombres
(defparameter *titulos*
'(Mr Mrs Don Seor Dr Sir)
"Lista de ttulos que pueden aparecer al inicio de un nombre")
TAPIA 2005-2006 14
Ms
IIIA

Defparameter es otra forma especial que define un parmetro, es decir,


una variable que no cambia a lo largo de la computacin.
As ahora podemos cambiar la implementacin.

(defun first-name (name)


"Bla bla bla"
(if (member (first name) *titulos*)
(first-name (rest name))
(first name)))

> (first-name '(Mr Dr Don Pepe Cuena)) Pepe

Haciendo una traza podemos ver que ocurre


> (trace first-name)
(FIRST-NAME)
TAPIA 2005-2006 15

Trace
IIIA

> (first-name '(Mr Dr Don Pepe Cuena))


(1 ENTER FIRST-NAME: (MR DR DON PEPE CUENA))
(2 ENTER FIRST-NAME: (DR DON PEPE CUENA))
(3 ENTER FIRST-NAME: (DON PEPE CUENA))
(4 ENTER FIRST-NAME: (PEPE CUENA))
(4 EXIT FIRST-NAME: PEPE)
(3 EXIT FIRST-NAME: PEPE)
(2 EXIT FIRST-NAME: PEPE)
(1 EXIT FIRST-NAME: PEPE)
PEPE

TAPIA 2005-2006 16
Funciones High-order
IIIA

Las funciones en LISP se pueden crear y llamar, como ya hemos visto,


pero tambien se pueden manipular como cualquier otro tipo de objeto. Ya
hemos visto un ejemplo de programacin high-order: mapcar.
(defun mappend (fn lista)
"Aplica fn a todos los elementos de lista y hace un append de los
resultados"
(apply #'append (mapcar fn lista)))
veamos como funciona el apply
> (apply #'+ '(1 2 3 4)) 10
> (apply #'append '((1 2 3) (a b c))) (1 2 3 a b c)
Definimos una funcin auxiliar
> (defun self-and-double (x) (list x (+ x x)))
> (self-and-double 3) (3 6)
> (apply #'self-and-double '(3)) (3 6)
> (mapcar #'self-and-double '(1 10 20)) ((1 2) (10 20) (20 40))
> (mappend #'self-and-double '(1 10 20)) (1 2 10 20 20 40)

TAPIA 2005-2006 17

Funcall and Lambda


IIIA

funcall es similar a apply con la diferencia sus argumentos no estan en una lista.
> (funcall #'+ 2 3) 5
> (apply #"+ '(2 3)) 5
> (funcall #'+ '(2 3)) Error (2 3) is not a number

Es posible definir funciones sin darles nombre. Esto se hace con la sintaxis
especial Lambda.
Russell x(x + x)
Church ^x(x + x) x(x + x) x(x + x) 1941
McCarthy (lambda (x) (+ x x)) 1958

En general (lambda (parameters ...) body ...)


una expresin lambda es un nombre noatmico para una funcin. As su uso es
exacto al de una funcin como append.
primer argumento de una llamada
> ((lambda (x) (+ x 2)) 4) 6
obtencin de la funcin real
> (funcall #'(lambda (x) (+ x 2)) 4) 6

TAPIA 2005-2006 18
Ms
IIIA

La forma de evaluacin es un poco ms complicado de lo explicado hasta ahora.


Si el primer elemento de una lista es una forma especial, la expresin se evalua
bajo las reglas de esa forma especial. Sin, el primer argumento es evaluado
como una funcin, pudiendo ser un smbolo o una funcin lambda, el resto de
elementos se evaluan como se ha explicado hasta ahora.
Cuando una funcin aparece en una posicin diferente de la primera debemos
utilizar #' sin las expresiones sern evaluadas de forma normal y no sern
tratadas como funciones.

> append Error: APPEND is not a bound variable


> (lambda (x) (+ x 2)) Error: Lambda is not a function

Hay dos razones que justifican la existencia de funciones lambda (sin nombre)
Provoca confusin crear nombres innecesarios de funciones en un programa.
Nos permite crear funciones en tiempo de ejecucin! Esta herramienta de
programacin es muy potente y no es posible usarla en la mayoria de lenguajes.
Estas funciones de tiempo de ejecucin se denominan clausuras o cierres.

TAPIA 2005-2006 19

Que hace a LISP diferente


IIIA

Soporte de listas

Manejo automtico del almacenamiento

Tipaje dinmico

Funciones como objetos de primera clase

Sintaxis uniforme

Entorno interactivo

Extensibilidad

Historia
TAPIA 2005-2006 20
LISP style
IIIA

Ser especfico
Ejemplo: When y if
Usar abstracciones
Ejemplo: last-name y caddar
Ser conciso
Ejemplo: find y loop
Usar las herramientas proporcionadas
Ejemplo: find
No ser oscuro
Ejemplo: otra vez find
Ser consistente
Ejemplo: usar siempre la misma primitiva para lo mismo

A veces hay conflictos


(setq x val) es ms especfico que (setf x val) pero setf es ms
consistente ya que sirve para ms ocasiones.

TAPIA 2005-2006 21

Special forms para definiciones


IIIA

Funciones
(defun function-name (parameter ...) "opt. doc." body...)
Macros
(defmacro macro-name (parameter ...) "opt. doc." body ...)
Variables
(defvar variable-name initial-value "opt. doc.")
La expresin initial-value es evaluada slo si la variable no tiene valor
cuando se le requiere. Es opcional.
Parmetros
(defparameter variable-name value "opt. doc.")
Constantes
(defconstant variable-name value "opt. doc.")
Estructuras
(defstruct structure-name "opt. doc." slot...)

Todas las formas def- definen smbolos globales. Para definir variables
y funciones locales es necesario utilizar let y labels.
TAPIA 2005-2006 22
Estructuras
IIIA

Veamos las estructuras


(defstruct name first (middle nil) last)
Se definen automticamente la funcin constructora make-name, el
predicado name-p, y las funciones accesoras name-first, name-middle y
name-last
> (setf b (make-name :first 'pepe :last 'cuena))
#S(NAME :FIRST PEPE :LAST CUENA)
> (name-first b) pepe
> (name-middle b) nil
> (name-last b) cuena
> (name-p b) T
> (name-p 'pepe) NIL
> (setf (name-middle b) 'Nolose) nolose
>b
#S(NAME :FIRST PEPE :MIDDLE NOLOSE :LAST CUENA)
TAPIA 2005-2006 23

Special forms para condicionales


IIIA

Hemos visto el if. Ahora veremos el cond y como las demas pueden expresarse
como estas
(cond (test result...)
(test result...)
...)
Evaluacin secuencial de los tests, cuando uno evalua diferente de nil se evalua
el (los) resultados a continuacin. Si ninguno evalua no-nil el resultado es nil. Se
devuelve el resultado de la ltima expresin evaluada.

(when test a b c)
(or a b c)
(if test (progn a b c))
(cond (test a b c)) (if a a (if b b c))
(unless test x y) (cond (a) (b) (c))
(if (not test) (progn x y)) (case a (b c) (t x))
(cond ((not test) x y)) (if (eql a 'b) c x)
(and a b c)
(cond ((eql a 'b) c) (t x))
(if a (if b c))
(cond (a (cond (b c))))

TAPIA 2005-2006 24
Special forms para manejar variables y
IIIA
posiciones
La forma especial setf es la utilizada para assignar valores a una variable o a una
posicin (variable generalizada).
LISP PASCAL
(setf x 0) x := 0;
(setf (aref A i j) 0) A[i,j] := 0;
(setf (rest list) nil) list^.rest := nil;
(setf (name-middle b) 'Q) b^.middle := "Q";
Las expresiones que se pueden encontrar a la izquierda de una sentencia de
asignacin en Pascal estn limitadas por la sintaxis de Pascal, en LISP es posible
definir nuevas expresiones a travs de las forma especial defsetf.
Hay otras formas especiales ms espcificas. Por ejemplo (rplacd list nil) tiene el
mismo efecto que (setf (rest list) nil)
Para asignar variables es muy comn el uso de setq.
En cualquier caso la programacin funcional pura no permite la asignacin, y no es
extrao ver programas en los que esta no aparece. La forma habitual es el uso
de la vinculacin en lugar de la asignacin. Es decir usar parmetros de funciones
o variables locales dentro de un let.
(let ((x 40) ((lambda (x y)
(y (+ 1 1))) (+ x y))
(+ x y)) 40 (+ 1 1))
TAPIA 2005-2006 25

Funciones y formas especiales para


IIIA
repeticin
dolist iter. sobre los elem. de una lista
dotimes iter. sobre enteros sucesivos
do, do* iter. general. Sintaxis sucinta
loop iter. general. Sintaxis prolija
mapc, mapcar iter. sobre elem. de una lista
some, every iter. sobre lista hasta condicin (notevery, notany)
(every #'characterp "abc")
find, reduce, ... funciones ms especficas
recursin repeticin general.
Para ver las diferencias haremos versiones de la funcin length.
(dolist (variable list optional-result) body...)

(defun length1 (lista)


(let ((len 0))
(dolist (element list)
(setf len (+ len 1)))
len))
TAPIA 2005-2006 26
IIIA

mapc tiene dos argumentos, uno una funcin y el otro una lista. Aplica la
funcin a cada elemento de la lista.

(defun length2 (lista)


(let ((len 0))
(mapc #'(lambda (element)
(incf len))
lista)
len))

TAPIA 2005-2006 27

Funciones y formas especiales para


IIIA
repeticin II
(dotimes (variable number optional-result) body...)

Dotimes no es apropiado para length, por supuesto.

(do ((variable initial next) ...)


(exit-test result)
body...)

(defun length3 (list)


(do ((len 0 (+ len 1))
(l list (rest list)))
((null l) len)))

TAPIA 2005-2006 28
IIIA

La sintaxis de loop representa un lenguaje en s misma. No es muy


utilizada debido a su caracter no funcional. Aqui vemos dos ejemplos.

(defun length4 (list)


(loop for element in list
count t))

(defun length5 (list)


(loop with len = 0
until (null list)
for element = (pop list)
do (incf len)
finally (return len)))

TAPIA 2005-2006 29

Funciones y formas especiales para


IIIA
repeticin III
Muchas formas de iteracin corresponden a esquemas de programacin,
como hemos visto con los casos de dolist o dotimes. LISP proporciona
flexibilidad para construir los esquemas ms adecuados. La flexibilidad
viene dada por tres elementos.
1) Aplicacin a un nmero arbitrario de listas.
> (mapcar #'- '(1 2 3) (-1 -2 -3)
> (mapcar #'+ '(1 2) '(10 20) (11 22)
> (mapcar #'+ '(1 2) '(10 20) '(100 200)) (111 222)
2) Palabras clave que varian las comprobaciones
> (remove 1 '(1 2 3 2 1 0 -1)) (2 3 2 0 -1)
> (remove 1 '(1 2 3 2 1 0 -1) :key #'abs) (2 3 2 0)
> (remove 1 '(1 2 3 2 1 0 -1) :test #'<) (1 1 0 -1)
> (remove 1 '(1 2 3 2 1 0 -1) :start 4) (1 2 3 2 0 -1)
3) Predicados en lugar de elementos
> (remove-if #'oddp '(1 2 3 2 1 0 -1)) (2 2 0)
> (remove-if-not #'oddp '(1 2 3 2 1 0 -1)) (1 3 1 -1)
> (find-if #'evenp '(1 2 3 2 1 0 -1)) 2
TAPIA 2005-2006 30
Funciones y formas especiales para
IIIA
repeticin III
En las prximas tablas usaremos los siguientes valores
(setf x '(a b c))
(setf y '(1 2 3))
Las funciones de la primera tabla no aceptan palabras clave.
(every #'oddp y) nil compr. que cada elem satisf. el pred
(some #'oddp y) t compr. si algn elem satisf. el pred.
(mapcar #'- y) (-1 -2 -3) aplica la fn a cada elem. y dev. Lista
(mapc #'print y) imprime 1 2 3 aplica la fn a cada elem.
Las siguientes funciones s que permiten las palabras clave.
(member 2 y) (2 3) ver si el elem. esta en la lista
(count 'b x) 1 contar el nm. de apariciones
(delete 1 y) (2 3) eliminar elementos
(find 2 y) 2 encontrar elementos
(position 'a x) 0 posicin de un elemento
(remove 2 y) (1 3) como delete pero con copia
(substitute 4 2 y) (1 4 3) reemplazar elementos

TAPIA 2005-2006 31

Repeticin via recursin


IIIA

Una de las caractersticas que histricamente caracteriz a LISP fue la


posibilidad de permitir recursin. La recursin es un mecanismo general de
realizar repeticin.

(defun length9 (lista)


(if (null lista) 0 (+ 1 (length9 (rest list)))))

Las versiones recursivas sobre listas son fciles de ver debido a la definicin
recursiva de las mismas. Una lista es o bien vacia o bien un elemento
concatenado a una lista.
Los rboles son difciles de manejar si no es a travs de recursin.
La ineficiencia es una objecin clsica a la recursin. Vease

(defun length10 (list) (length10-aux list 0))

(defun length10-aux (sublist len-so-far)


(if (null sublist)
len-so-far
(length10-aux (rest sublist) (+ 1 len-so-far))))
TAPIA 2005-2006 32
IIIA

La segunda versin es recursiva por la cola. Los compiladores pueden


mejorar la eficiencia de estas funciones.
Las dos versiones pueden combinarse de forma elegante en CommonLisp

(defun length11 (lista &optional (len-so-far 0))


(if (null lista) len-so-far
(length11 (rest lista) (+ 1 len-so-far))))

TAPIA 2005-2006 33

Repeticin via recursin


IIIA

Otra posibilidad de aumentar la elegancia es introducir funciones


locales!

(defun length12 (lista)


(labels
((length13 (la-lista len-so-far)
(if (null la-lista)
len-so-far
(length13 (rest la-lista) (+ 1 len-so-far))))
(length13 lista 0)))

La forma especial labels es la forma de definir funciones locales

(labels
((function-name (parameter...) function-body...) ...)
body-of-labels)

TAPIA 2005-2006 34
Otras formas especiales
IIIA

Hay otras formas especiales que no encajan en los tipos anteriores hemos visto
ya 'x (quote x) y #'f (function f)

> (progn (setf x 0) (setf x (+ x 1)) x) 1


> (trace length9) (length9)
> (length9 '(a b c))

(1 ENTER LENGTH: (A B C))


(2 ENTER LENGTH9: (B C))
(3 ENTER LENGTH9: (C))
(4 ENTER LENGTH9: NIL)
(4 EXIT LENGHT9: 0)
(3 EXIT LENGTH9: 1)
(2 EXIT LENGTH9: 2)
(1 EXIT LENGTH9: 3)
3
>
TAPIA 2005-2006 35

IIIA

> (untrace length9) (length9)


> (length9 '(a b c)) 3
Finalmente la forma especial return sirve para salir de un bloque de cdigo. Los bloques se
construyen con la forma especial block or por las formas de iteracin do, do*, dolist, dotimes
o loop.
(defun product (numbers)
(let ((prod 1))
(dolist (n numbers prod)
(if (= n 0) (RETURN 0) (setf prod (* n prod))))))

TAPIA 2005-2006 36
Macros
IIIA

Muchas de las formas especiales que hemos comentado no son tales formas. Son
macros que el compilador expande en tiempo de compilacin. LISP proporciona un
conjunto de macros predefinidas y permite al usuario definir nuevas macros. Las
macros se definen con la foma especial defmacro. Para construir una macro hay
que plantearse varias cosas:
Es necesaria la macro?
Escribir la sintaxis de la macro.
Imaginar en que debe expandirse la macro.
Escribir el cdigo de la macro usando defmacro.
Para la macro while una sintaxis puede ser
(while test body...)
la expansin ser (loop (unless test (return nil)) body...)
la definicin es
(defmacro while (test &rest body)
(list* 'loop
(list 'unless test '(return nil))
body))

TAPIA 2005-2006 37

Macros
IIIA

La expansin se puede ver con la ayuda de la funcin macroexpand-1.

> (macroexpand-1 '(while (< i 10)


(print (* i i))
(setf i (+ i 1))))

(LOOP (UNLESS (< I 10) (RETURN NIL))


(PRINT (* I I)) (SETF I (+ I 1)))

> (setf i 7) 7
> (while (< i 10)
(print (* i i))
(setf (+ i 1)))
49
64
81
nil

TAPIA 2005-2006 38
Notacin backquote
IIIA

La parte ms complicada de las macros es definir el cdigo para la expansin.


Hay una notacin en CommonLisp que ayuda a este propsito.
la backquote "`" significa que en la expresin a continuacin nada se evaluar a
no ser que vaya precedido de "," o de ",@", la diferencia est en que la expresin
precedida de ",@" debe evaluar a una lista, y el efecto es que el nivel superior
de parntesis desaparecer.

(defmacro while (test &rest body)


`(loop (unless ,test (return nil)) ,@body))

Al final de una lista ",@" tiene el mismo efecto que "." seguido de ",".

> (setf test1 '(a test)) (a test)


> `(this is ,test1) (this is (a test))
> `(this is ,@test1) (this is a test)
> `(this is . ,test1) (this is a test)
> `(this is ,@test1 -- this is only ,@test1) (this is a test -- this is only a test)

TAPIA 2005-2006 39

Funciones sobre listas


IIIA

En la siguiente tabla usaremos

(setf x '(a b c))


(setf y '(1 2 3))

(first x) a primer elem. de lista


(second x) b segundo elem. de lista
(third x) c tercer elem. de lista
(nth 0 x) a n-simo elem. de lista
(rest x) (b c) todos los elem. de lista menos primero
(car x) (first x)
(cdr x) (rest x)
(last x) (c) ltima clula cons de una lista
(length x) 3 nmero de elems. de una lista
(reverse x) (c b a) lista invertida
TAPIA 2005-2006 40
Listas
IIIA

(cons 0 y) (0 1 2 3) operacin de const. de listas


(append x y) (a b c 1 2 3) unir juntos los elems.
(list x y) ((a b c) (1 2 3)) hacer una nueva lista
(list* 1 2 x) (1 2 a b c) append del lt. arg. a los otros
(null nil) t el pred. es cierto en listas vacias
(null x) nil y falso en otro caso
(listp x) t pred. cierto para una lista
(listp 3) nil y falso en otro caso
(consp x) t pred. es cierto en no-nil listas
(consp nil) nil y falso para tomos incluido nil
(equal x x) t cierto para listas iguales

TAPIA 2005-2006 41

IIIA

(equal x y) nil y falso para listas diferentes


(sort y #'>) (3 2 1) ordena una lista segn un criterio
(subseq x 1 2) (b) subsecuencia desde inicio a fin

En el caso de que en (cons a b), b no sea una lista no se trata de un


error. El resultado es (a . b). Esta notacin es conocida como par
puntual. (first (cons a b)) a, (rest (cons a b)) b.
La representacin de las listas se basa en las celulas cons.

(uno dos tres)

uno Dos Tres

TAPIA 2005-2006 42
Igualdad y representacin interna
IIIA

Hay cinco predicados de igualdad en LISP. = se utiliza slo para


nmeros.
Cuando LISP lee un smbolo en dos lugares diferentes garantiza que
sean el mismo smbolo. Ahora bien cuando una lista se lee en dos sitios
no se garantiza que sea exactamente la misma.
(setf x '(uno dos))

uno Dos

(setf y '(uno dos))

(cons 'cero x) x

cero uno Dos

TAPIA 2005-2006 y 43

Igualdad y representacin interna II


IIIA

y eq eql equal equalp

'x 'x T T T T
'0 '0 ? T T T
'(X) '(X) NIL NIL T T
'"XY" '"XY" NIL NIL T T
'"xY" '"Xy" NIL NIL NIL T
'0 '0.0 NIL NIL NIL T
'0 '1 NIL NIL NIL NIL

TAPIA 2005-2006 44
Funciones sobre secuencias
IIIA

Los LISP originales nicamente disponan de smbolos y listas como


estructuras de datos. LISPs ms modernos como CommonLisp proveen
de otras estructuras. Entre ellas se encuentran las secuencias. Las
listas son un caso particular de secuencia. Las funciones de manipulacin
de las mismas dependen del tipo de secuencia. Hay algunas funciones
como mapcar que slo trabajan sobre listas. Otras como concatenate son
genricas.

(nth n list)
(elt sequence n)
(aref array n)
(char string n)
(bit bitvector n)
(sbit simplebitvector n)
(svref simplevector n)

TAPIA 2005-2006 45

Funciones sobre tablas


IIIA

Las listas de asociacin son listas utilizadas para implantar tablas. Una
lista de asociacin es una lista de pares puntuales donde cada par es del
tipo (clave . valor). Dada una clave se puede obtener el valor de la tabla.
> (setf state-table '((AL . Alabama) (AK . Alaska) (AZ . Arizona)))
> (assoc 'ak state-table) (AK . Alaska)
> (cdr (assoc 'ak state-table)) Alaska
> (assoc 'tx state-table) nil
Tambin se puede acceder por valor
> (rassoc 'arizona state-table) (AZ . Arizona)
> (car (rassoc 'arizona state-table)) AZ
Las tablas hechas con listas de asociacin se manejan de forma simple,
pero son ineficientes. LISP da la posibilidad de definir tablas de hash.
> (setf table (make-hash-table))
> (setf (gethash 'AL table) 'Alabama)
> (setf (gethash 'AK table) 'Alaska)
> (setf (gethash 'AZ table) 'Arizona)

TAPIA 2005-2006 46
Funciones sobre tablas
IIIA

> (gethash 'AK table) Alaska


> (gethash 'TX table) nil

La funcin remhash borra una pareja clave/valor de una tabla, clrhash las borra
todas y maphash se puede usar para recorrer todas las parejas.

La tercera forma de hacer tablas es mediante las listas de propiedad. Son


parecidas a las a-list.
a-list: ((key1 . val1) (key2 . val2) ...)
p-list: (key1 val1 key2 val2 ...)
La diferencia en su uso es que cada smbolo posee una p-list asociada. Los
valores de las propiedades se obtienen a traves de la funcin get.
> (setf (get 'state 'AL) 'Alabama)
> (setf (get 'state 'AK) 'Alaska)
> (setf (get 'state 'AZ) 'Arizona)
> (get 'state 'AK) Alaska
> (get 'state 'TX) nil
No hay equivalente de rassoc. Habra que hacerlo colocando otra propiedad
(Abrev por ejemplo).
TAPIA 2005-2006 47

Smbolos
IIIA

o symbol-value
o symbol-function
o symbol-plist
o symbol-name
o symbol-package
o symbolp

o inspect

ocompile

TAPIA 2005-2006 48
Funciones sobre arboles
IIIA

Muchas funciones de LISP tratan expresiones del tipo


( (a) ((b (c) (d e)) a) ) como rboles.
La funcin copy-tree hace una copia del rbol y tree-equal es similar a equal,
pero permite :test.
> (setf tree '((a b) ((c)) (d e)))
> (tree-equal tree (copy-tree tree)) T

Hay funciones que permiten realizar substituciones de expresiones.


> (subst 'new 'old '(old ((very old)))) (new ((very new)))
> (sublis '((old . new)) '(old ((very old))) (new ((very new)))
> (subst 'new 'old 'old) 'new
(defun english->french (words)
(sublis '((are . va) (book . livre) (friend . ami) (hello . bonjour)
(how . comment) (my . mon) (red . rouge) (you . tu))
worgs))
> (english->french '(hello my friend -- how are you today?))
(bonjour mon ami -- comment va tu today?)
TAPIA 2005-2006 49

Funciones numricas
IIIA

(+ 4 2) 6 suma
(- 4 2) 2 resta
(* 4 2) 8 multiplicacin
(/ 4 2) 2 divisin
(> 100 99) T mayor que (tambin >=)
(= 100 100) T igual que (tambin /=)
(< 99 100) T menor que (tambin <=)
(random 100) 42 nmeros enteros aleatorios
(expt 4 2) 16 exponenciacin (tambien exp, y log)
(sin pi) 0.0 seno (tambin cos, tan, ...)
(asin 0) 0.0 arcoseno (tambin acos, atan, etc)

TAPIA 2005-2006 50
IIIA

(min 2 3 4) 2 mnimo (tambin max)


(abs -3) 3 valor absoluto
(sqrt 4) 2 raiz cuadrada
(round 4.1) 4 redondeo(tamb. truncate, floor, etc)
(rem 11 5) 1 resto (tambin mod)

TAPIA 2005-2006 51

Funciones sobre conjuntos


IIIA

Uno de los usos de LISP es tratar las listas como conjuntos. Para ello
proporciona un conjunto de funciones. Usaremos los siguientes valores

(setf r '(a b c d)) (a b c d)


(setf s '(c d e)) (c d e)

(intersection r s) (c d) interseccin
(union r s) (c d) unin
(set-difference r s) (a b) r-s
(member 'd r) (d) ver si el elem. perten. al conj.
(subsetp s r) nil ver si es subconjunto
(adjoin 'b s) (b c d e) aadir un elemento a un conj.
(adjoin 'c s) (c d e) pero sin duplicar

Otra posibilidad es utilizar secuencias de bits para representar


conjuntos de un universo de elementos reducido. La computacin es en
este caso ms eficiente.
TAPIA 2005-2006 52
Funciones destructivas
IIIA

Las funciones matemticas slo calculan resultados a partir de valores pero no


"hacen" nada. Algunas funciones de LISP pueded "hacer" algo aparte de la propia
computacin. En otros lenguajes a estas funciones se las denomina
procedimientos, y pueden causar graves trastornos si no se utilizan con
precaucin. A veces, en cambio, son de gran utilidad.
> (setf x '(a b c)) (a b c)
> (setf y '(1 2 3)) (1 2 3)
> (append x y) (a b c 1 2 3)
append es una funcin pura. no modifica ni x ni y, en cambio.
> (nconc x y) (a b c 1 2 3)
> x (a b c 1 2 3)
> y (1 2 3)
calcula exactamente lo mismo que append pero modifica el primer argumento. Se
llama destructiva, dado que destruye estructuras preexistentes modificandolas
por nuevas. La ventaja es el espacio de almacenamiento ahorrado.
Otras funciones destructivas son: nreverse, nintersection, nunion, nset-
difference y nsubst.
Un caso especial es delete, version destructiva de remove.
TAPIA 2005-2006 53

Ordenacin
IIIA

o Ordenacin de secuencias
o destructiva

o (sort (3 4 6 1 78 3 7) #<)
o (sort gadeedpkmk #'char-lessp)
o (sort '("Josep" "Ramon" "Laura" "Joan") #'string-lessp)
o (sort ((3 2 4) (4 ji true) (32 4 5) (9 8 7)) #'> :key #'car)

TAPIA 2005-2006 54
Entrada/salida
IIIA

La entrada en LISP es muy fcil ya que el lenguaje provee al usuario de un


parser completo cuyo nombre es read. Se utiliza para leer y devolver espresiones
LISP. Si la entrada se puede adaptar para que pueda escribirse en formato de
expresiones LISP, los problemas de entrada se han acabado.
Para leer desde el terminal las funciones read, read-char y read-line devuelven
una expresin, un carcter y una cadena respectivamente.
Para leer de un fichero la funcin with-open-stream es la ms comunmente
utilizada. Asocia un stream a un fichero. Las funciones de lectura tienen un
parmetro opcional que es precisamente el nombre de un stream.
Las funciones de salida son print que imprime cualquier objeto en una nueva linea
dejando un blanco despus. prin1 es igual pero sin salto de linea ni blanco. Los
formatos generados por estas funciones son leibles por las funciones de
entrada.La funcin ms utilizada es el format (todo un lenguaje de escritura).
> (with-open-file (stream "Mifichero.txt" :direction :output)
(print '(hello there) stream)
(princ 'goodbye)) goodbye ; y crea el fichero mifichero.txt
> (with-open-file (stream "Mifichero.txt" :direction :input)
(list (read stream) (read-char stream) (read stream)
(read stream nil 'eof)))
((hello there) #\g oodbye eof)
TAPIA 2005-2006 55

IIIA

> (let ((numbers '(1 2 3 4 5)))


(format t "~&~{~ r~^ plus ~} is ~ @r"
numbers (apply #'+ numbers)))
one plus two plus three plus four plus five is XV

(loop (print (eval (read))))

TAPIA 2005-2006 56
Herramientas de depuracin
IIIA

En la mayoria de lenguajes hay dos estrategias de depuracin:


(1) editar el programa y insertar sentencias de impresin
(2) utilizar un programa depurador que altere el estado interno en
tiempo de ejecucin.

En LISP hay una tercera que es (3) hacer anotaciones que no son parte del
programa pero que automticamente alteran la ejecucin del mismo.

Este es el caso de trace y untrace que ya hemos visto. Otro caso es step. (step
expression). Evalua la expresin dando informacin de cada paso de evaluacin.

Otras funciones son:


(apropos 'string) Devuelve todos los simbolos que hacen matching con string.
(describe 'make-string) Da informacin sobre el smbolo.
(documentation 'first 'function) devuelve la cadena de documentacin de la funcin
first.
Si se quiere mirar y tal vez modificar los componentes de una estructura, la
herramienta es inspect.

TAPIA 2005-2006 57

Valores mltiples
IIIA

Hay funciones en lisp que no se comportan como funciones en el sentido que no


devuelven un nico valor. Por ejemplo
(round 5.1) 5 .1
Hay dos valores despus de la flecha porque round devuelve el entero y el resto.
La mayoria de las veces los valores mltiples son ignorados y slo se considera el
primero de ellos.
(* 2 (round 5.1)) 10
Si se quieren obtener todos se debe hacer con la forma especial multiple-value-
bind.

(defun show-both (x)


(multiple-value-bind (int rem)
(round x)
(format t "~f = ~d + ~f" x int rem)))
> (show-both 5.1)
5.1 = 5 + 0.1

Tambin se pueden construir funciones que devuelvan mltiples valores.


(values 1 2 3) 1 2 3
TAPIA 2005-2006 58
Que hacer para continuar
IIIA

Hay varios libros interesantes para aprender tcnicas de programacin en LISP.


Los mejores son los de Abelson Sussman and Susman y el Norvig.

Peter Norvig: Artificial Intelligence Programming: Case Studies in Common Lisp

El manual del Lenguaje es:

Steele Jr., Guy L : CommonLISP the language second edition. Digital Press.

Paul Graham: On Lisp

o Multiprocessing
o Compiler
o Delivery
o Debugger
o
TAPIA 2005-2006 59

Potrebbero piacerti anche