introducciÓn al lenguage common lisp › ~puyol › tapia › transpas › lisp2005.pdf · lisp...

30
IIIA 2005-2006 INTRODUCCIÓN AL LENGUAGE COMMON LISP IIIA TAPIA 2005-2006 2 Introduction

Upload: others

Post on 23-Jun-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA 2005-2006

INTRODUCCIÓN AL LENGUAGE COMMON LISP

IIIA

TAPIA 2005-2006 2

Introduction

Page 2: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 3

Introducción

Bibliografia básica:

- Peter Norvig: Artificial IntelligenceProgramming: Case Studies in Common Lisp- Steele Jr., Guy L : CommonLISP the language second edition. Digital Press

TAPIA Site (Paul Graham)Implementaciones de CommonLisp:

MCLHarlequinAllegroLispWorks (+ CAPI)

www.lispworks.comwww.franz.comwww.digitool.com

CLOS (Object System)CLIM (Interface Manager)

IIIA

TAPIA 2005-2006 4

Introducción: LIST Processing

Cuando se inicia la ejecución de LISP siempre aparece un prompt como >Después se puede teclear y obtener resultados> (+ 2 2)4Las expresiones aritméticas siguen la notación prefija. Los resultadosde los cálculos son impresos por el evaluador. La notación préfija es máscompacta que la infija> (+ 1 2 3 4 5 6 7 8 9 10) 55> (- (+ 9000 900 90 9) (+ 5000 500 50 5)) 4444Las expresiones se pueden anidar. La regla de evaluación es mucho mássimple que la usual en matemáticas u otros lenguajes de programación. Primero se evaluan los argumentos y posteriormente se aplica la funciónsobre los resultados de la evaluación.Una diferencia inicial para programadores de otros lenguajes de programación es que no hay diferencia entre expresión y sentencia. en C 2 + 2 tiene un valor, en cambio x = 2 + 2 no. En LISP toda expresión, tenga efecto o no, devuelve un valor.

Page 3: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 5

Symbolic Computation

Las reglas léxicas son mucho más simples en LISP. Solo hay paréntesis, comillas (sencilla, doble y backquote) espacios y comas. El punto y coma no separa expresiones (no es necesario debido a los paréntesis) sino queinicia comentarios.

LISP permite la manipulación de símbolos, y la construcción de estructuras de datos complejos a partir de ellos.> (append '(Carlos Antonio) '(Carmen Rosa))(CARLOS ANTONIO CARMEN ROSA)La parte extraña es el ('), que sirve para bloquear la evaluación de unaexpresión y devolverla literalmente.> '(Carlos Antonio) (CARLOS ANTONIO)> 'A A > (quote A) A> '2 2> 2 2

IIIA

TAPIA 2005-2006 6

Symbolic Computation

> '(+ 2 2) (+ 2 2)> (+ 2 2) 4> A Error: A is not a bound variable> (Carlos 'Antonio) Error: Carlos is not a functionLos cálculos simbólicos y numéricos se pueden mezclar.> (+ 2 (length '(a b c d))) 6

LISP no otorga ninguna semántica a los símbolos que manipula.CommonLISP contiene un conjunto de funciones predefinidas que esnecesario conocer. Como +, append, length.

Los símbolos en CommonLISP no son casesensitive.Muchos signos de puntuación son autorizados para formar parte de los símbolos: '?!$/<=>'

Page 4: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 7

Variables

Los símbolos 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 símbolos se utilizan también para dar nombre a las funciones. Un mismo símbolo puede ser a la vez nombre de una variable y nombre de una función.

IIIA

TAPIA 2005-2006 8

Special forms

En los ejemplos anteriores setf viola la regla de evaluación. No evalua susargumentos y luego aplica la función al resultado de esta evaluación. Setfno es una función. Se trata de uno de los componentes de la sintaxisbásica de LISP. A las expresiones sintácticas de LISP se las conocecomo Special forms. Por ejemplo,

(setf x (+ 1 2) )

A veces se denomina Special form a los símbolos como setf y a veces a las expresiones encabezadas por estos símbolos, lo cual puede crear unacierta confusión.

A lo largo de esta introducción veremos unos cuantas special forms de CommonLisp.

Page 5: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 9

Listas

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) 4Algunos detalles sobre listas. rest (o cdr) devuelve la lista resultante de eliminar el primer elemento de la lista argumento. NIL y () son completamenteequivalentes. NIL también 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

IIIA

TAPIA 2005-2006 10

Listas

Aparte de acceder a los elementos de las listas, también podemosconstruir listas.> p (esto es una asignación)> (cons 'porque p) (porque esto es una asignación)> (cons (first p) (rest p)) (esto es una asignación)> (setf ciudad (list 'Paris 'Roma)) (paris roma)> (list p 'de (list ciudad) 'tachin) ((esto es una asignacion) de ((parisroma)) 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

Page 6: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 11

Bases listas

o Para las listas solo es necesarioo Lectura

o firsto Rest

o Escriturao conso nil

IIIA

TAPIA 2005-2006 12

Funciones

La forma especial defun viene de "define function". Se utiliza para definirfunciones.(defun last-name (name)

"Selecciona el apellido de un nombre representado como una lista. (en formato sajón)"

(first (last name)))La función recibe un nombre last-name, tiene una lista de parámetros quecontiene un único parámetro (name). También tiene una cadena de documentaciónque dice que es lo que la función hace. El cuerpo de la función es (first (last name)). En general (defun function-name (parameter ...)

"Documentation string"function-body ...)

Una vez definida, la función se puede utilizar como cualquier otra función LISP.> (last-name '(John Q Smith)) SMITH> (last-name '(Antonio De las Cruces Revueltas)) REVUELTAS> (last-name '(Aristoteles)) Aristoteles

Page 7: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 13

Funciones

Podemos definir la función 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) (Señor Pepe Galvez)(Don Pepe Cuena) (Mr Carlos Sierra)))

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

> (mapcar #'last-name nombres)(LOPEZ GALVEZ CUENA SIERRA)

IIIA

TAPIA 2005-2006 14

Utilizando funciones

La notación #' relaciona el nombre de la función con la función misma. En este sentido es similar con la notación 'x. La llamada a mapcar anterior es equivalente a (list (last-name (first nombres))

(last-name (second nombres))...)

Mapcar viene de "to map" una función sobre los sucesivos car delosargumentos. Car viene de "contents of the address register" y cdr de "contents of the decrement register" las instrucciones utilizadas en la primera implementación 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 títulos honoríficos de los nombres(defparameter *titulos*

'(Mr Mrs Don Señor Dr Sir)"Lista de títulos que pueden aparecer al inicio de un nombre")

Page 8: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 15

Más

Defparameter es otra forma especial que define un parámetro, es decir, una variable que no cambia a lo largo de la computación.Así ahora podemos cambiar la implementación.

(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)

IIIA

TAPIA 2005-2006 16

Trace

> (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

Page 9: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 17

Funciones High-order

Las funciones en LISP se pueden crear y llamar, como ya hemos visto, pero tambien se pueden manipular como cualquier otro tipo de objeto. Yahemos visto un ejemplo de programación 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 función 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)

IIIA

TAPIA 2005-2006 18

Funcall and Lambda

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 sintaxisespecial Lambda.Russell x(x + x)Church ^x(x + x) Λx(x + x) λx(x + x) 1941McCarthy (lambda (x) (+ x x)) 1958

En general (lambda (parameters ...) body ...)una expresión lambda es un nombre noatómico para una función. Así su uso esexacto al de una función como append.primer argumento de una llamada> ((lambda (x) (+ x 2)) 4) 6obtención de la función real> (funcall #'(lambda (x) (+ x 2)) 4) 6

Page 10: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 19

Más

La forma de evaluación es un poco más complicado de lo explicado hasta ahora. Si el primer elemento de una lista es una forma especial, la expresión se evaluabajo las reglas de esa forma especial. Sinó, el primer argumento es evaluadocomo una función, pudiendo ser un símbolo o una función lambda, el resto de elementos se evaluan como se ha explicado hasta ahora.Cuando una función aparece en una posición diferente de la primera debemosutilizar #' sinó las expresiones serán evaluadas de forma normal y no serántratadas 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 confusión crear nombres innecesarios de funciones en un programa.• Nos permite crear funciones en tiempo de ejecución! Esta herramienta de programación es muy potente y no es posible usarla en la mayoria de lenguajes. Estas funciones de tiempo de ejecución se denominan clausuras o cierres.

IIIA

TAPIA 2005-2006 20

Que hace a LISP diferente

• Soporte de listas

• Manejo automático del almacenamiento

• Tipaje dinámico

• Funciones como objetos de primera clase

• Sintaxis uniforme

• Entorno interactivo

• Extensibilidad

• Historia

Page 11: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 21

LISP style

• Ser específicoEjemplo: When y if

• Usar abstraccionesEjemplo: last-name y caddar

• Ser concisoEjemplo: find y loop

• Usar las herramientas proporcionadasEjemplo: find

• No ser oscuroEjemplo: otra vez find

• Ser consistenteEjemplo: usar siempre la misma primitiva para lo mismo

A veces hay conflictos(setq x val) es más específico que (setf x val) pero setf es más

consistente ya que sirve para más ocasiones.

IIIA

TAPIA 2005-2006 22

Special forms para definiciones

• 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 expresión initial-value es evaluada sólo si la variable no tiene valor cuando se le requiere. Es opcional.• Parámetros

(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 símbolos globales. Para definir variables y funciones locales es necesario utilizar let y labels.

Page 12: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 23

Estructuras

Veamos las estructuras(defstruct name first (middle nil) last)

Se definen automáticamente la función 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)

IIIA

TAPIA 2005-2006 24

Special forms para condicionales

Hemos visto el if. Ahora veremos el cond y como las demas pueden expresarsecomo estas

(cond (test result...)(test result...)...)

Evaluación secuencial de los tests, cuando uno evalua diferente de nil se evaluael (los) resultados a continuación. Si ninguno evalua no-nil el resultado es nil. Se devuelve el resultado de la última expresión evaluada.

(when test a b c)(if test (progn a b c))(cond (test a b c))

(unless test x y)(if (not test) (progn x y))(cond ((not test) x y))

(and a b c)(if a (if b c))(cond (a (cond (b c))))

(or a b c)(if a a (if b b c))(cond (a) (b) (c))

(case a (b c) (t x))(if (eql a 'b) c x)(cond ((eql a 'b) c) (t x))

Page 13: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 25

Special forms para manejar variables y posiciones

La forma especial setf es la utilizada para assignar valores a una variable o a unaposición (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 asignación en Pascal están limitadas por la sintaxis de Pascal, en LISP es posibledefinir nuevas expresiones a través de las forma especial defsetf.Hay otras formas especiales más espécificas. Por ejemplo (rplacd list nil) tiene el mismo efecto que (setf (rest list) nil)Para asignar variables es muy común el uso de setq.En cualquier caso la programación funcional pura no permite la asignación, y no esextraño ver programas en los que esta no aparece. La forma habitual es el usode la vinculación en lugar de la asignación. Es decir usar parámetros de funcioneso variables locales dentro de un let.(let ((x 40) ((lambda (x y)

(y (+ 1 1))) (+ x y))(+ x y)) 40 (+ 1 1))

IIIA

TAPIA 2005-2006 26

Funciones y formas especiales pararepetición

Para ver las diferencias haremos versiones de la función length.(dolist (variable list optional-result) body...)

(defun length1 (lista)(let ((len 0))

(dolist (element list)(setf len (+ len 1)))

len))

dolist iter. sobre los elem. de una listadotimes iter. sobre enteros sucesivosdo, do* iter. general. Sintaxis sucintaloop iter. general. Sintaxis prolijamapc, mapcar iter. sobre elem. de una listasome, every iter. sobre lista hasta condición (notevery, notany)

(every #'characterp "abc")find, reduce, ... funciones más específicasrecursión repetición general.

Page 14: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 27

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

(defun length2 (lista)(let ((len 0))(mapc #'(lambda (element)

(incf len))lista)

len))

IIIA

TAPIA 2005-2006 28

Funciones y formas especiales pararepetición 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)))

Page 15: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 29

La sintaxis de loop representa un lenguaje en sí misma. No es muyutilizada 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)))

IIIA

TAPIA 2005-2006 30

Funciones y formas especiales pararepetición III

Muchas formas de iteración corresponden a esquemas de programación, como hemos visto con los casos de dolist o dotimes. LISP proporcionaflexibilidad para construir los esquemas más adecuados. La flexibilidadviene dada por tres elementos.1) Aplicación a un número 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

Page 16: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 31

Funciones y formas especiales pararepetición III

En las próximas 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 algún 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 núm. de apariciones(delete 1 y) (2 3) eliminar elementos(find 2 y) 2 encontrar elementos(position 'a x) 0 posición de un elemento(remove 2 y) (1 3) como delete pero con copia(substitute 4 2 y) (1 4 3) reemplazar elementos

IIIA

TAPIA 2005-2006 32

Repetición via recursión

Una de las características que históricamente caracterizó a LISP fue la posibilidad de permitir recursión. La recursión es un mecanismo general de realizar repetición.

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

Las versiones recursivas sobre listas son fáciles de ver debido a la definiciónrecursiva de las mismas. Una lista es o bien vacia o bien un elementoconcatenado a una lista. Los árboles son difíciles de manejar si no es a través de recursión.La ineficiencia es una objeción clásica a la recursión. 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))))

Page 17: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 33

La segunda versión es recursiva por la cola. Los compiladores puedenmejorar 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))))

IIIA

TAPIA 2005-2006 34

Repetición via recursión

Otra posibilidad de aumentar la elegancia es introducir funcioneslocales!

(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)

Page 18: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 35

Otras formas especiales

Hay otras formas especiales que no encajan en los tipos anteriores hemos vistoya '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>

IIIA

TAPIA 2005-2006 36

> (untrace length9) (length9)

> (length9 '(a b c)) 3

Finalmente la forma especial return sirve para salir de un bloque de código. Los bloques se construyen con la forma especial block or por las formas de iteración do, do*, dolist, dotimeso loop.

(defun product (numbers)

(let ((prod 1))

(dolist (n numbers prod)

(if (= n 0) (RETURN 0) (setf prod (* n prod))))))

Page 19: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 37

Macros

Muchas de las formas especiales que hemos comentado no son tales formas. Son macros que el compilador expande en tiempo de compilación. 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 código de la macro usando defmacro.Para la macro while una sintaxis puede ser

(while test body...)la expansión será (loop (unless test (return nil)) body...)la definición es

(defmacro while (test &rest body)(list* 'loop

(list 'unless test '(return nil))body))

IIIA

TAPIA 2005-2006 38

Macros

La expansión se puede ver con la ayuda de la función 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)))

496481nil

Page 20: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 39

Notación backquote

La parte más complicada de las macros es definir el código para la expansión. Hay una notación en CommonLisp que ayuda a este propósito.la backquote "`" significa que en la expresión a continuación nada se evaluará a no ser que vaya precedido de "," o de ",@", la diferencia está en que la expresiónprecedida de ",@" debe evaluar a una lista, y el efecto es que el nivel superior de paréntesis 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)

IIIA

TAPIA 2005-2006 40

Funciones sobre listas

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 célula cons de una lista(length x) 3 número de elems. de una lista(reverse x) (c b a) lista invertida

Page 21: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 41

Listas

(cons 0 y) (0 1 2 3) operación 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

IIIA

TAPIA 2005-2006 42

(equal x y) nil y falso para listas diferentes(sort y #'>) (3 2 1) ordena una lista según 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 notación es conocida como par puntual. (first (cons a b)) a, (rest (cons a b)) b.La representación de las listas se basa en las celulas cons.

uno Dos Tres

(uno dos tres)

Page 22: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 43

Igualdad y representación interna

Hay cinco predicados de igualdad en LISP. = se utiliza sólo paranúmeros.Cuando LISP lee un símbolo en dos lugares diferentes garantiza quesean el mismo símbolo. Ahora bien cuando una lista se lee en dos sitiosno se garantiza que sea exactamente la misma.

uno Dos

(setf x '(uno dos))

x

uno Dos

(setf y '(uno dos))

y

cero

(cons 'cero x)

IIIA

TAPIA 2005-2006 44

Igualdad y representación interna II

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

Page 23: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 45

Funciones sobre secuencias

Los LISP originales únicamente disponían de símbolos y listas comoestructuras de datos. LISPs más modernos como CommonLisp proveende otras estructuras. Entre ellas se encuentran las secuencias. Las listas son un caso particular de secuencia. Las funciones de manipulaciónde las mismas dependen del tipo de secuencia. Hay algunas funcionescomo mapcar que sólo trabajan sobre listas. Otras como concatenate son genéricas.

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

IIIA

TAPIA 2005-2006 46

Funciones sobre tablas

Las listas de asociación son listas utilizadas para implantar tablas. Unalista de asociación 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) nilTambién se puede acceder por valor> (rassoc 'arizona state-table) (AZ . Arizona)> (car (rassoc 'arizona state-table)) AZLas tablas hechas con listas de asociación 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)

Page 24: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 47

Funciones sobre tablas

> (gethash 'AK table) Alaska> (gethash 'TX table) nil

La función remhash borra una pareja clave/valor de una tabla, clrhash las borratodas 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 símbolo posee una p-list asociada. Los valores de las propiedades se obtienen a traves de la función get.> (setf (get 'state 'AL) 'Alabama)> (setf (get 'state 'AK) 'Alaska)> (setf (get 'state 'AZ) 'Arizona)> (get 'state 'AK) Alaska> (get 'state 'TX) nilNo hay equivalente de rassoc. Habría que hacerlo colocando otra propiedad(Abrev por ejemplo).

IIIA

TAPIA 2005-2006 48

Símbolos

o symbol-valueo symbol-functiono symbol-plisto symbol-nameo symbol-packageo symbolp

o inspect

ocompile

Page 25: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 49

Funciones sobre arboles

Muchas funciones de LISP tratan expresiones del tipo( (a) ((b (c) (d e)) a) ) como árboles.La función 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?)

IIIA

TAPIA 2005-2006 50

Funciones numéricas

(+ 4 2) 6 suma(- 4 2) 2 resta(* 4 2) 8 multiplicación(/ 4 2) 2 división(> 100 99) T mayor que (también >=)(= 100 100) T igual que (también /=)(< 99 100) T menor que (también <=)(random 100) 42 números enteros aleatorios(expt 4 2) 16 exponenciación (tambien exp, y log)(sin pi) 0.0 seno (también cos, tan, ...)(asin 0) 0.0 arcoseno (también acos, atan, etc)

Page 26: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 51

(min 2 3 4) 2 mínimo (también 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 (también mod)

IIIA

TAPIA 2005-2006 52

Funciones sobre conjuntos

Uno de los usos de LISP es tratar las listas como conjuntos. Para elloproporciona 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) intersección(union r s) (c d) unión(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) añadir un elemento a un conj.(adjoin 'c s) (c d e) pero sin duplicar

Otra posibilidad es utilizar secuencias de bits para representarconjuntos de un universo de elementos reducido. La computación es en este caso más eficiente.

Page 27: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 53

Funciones destructivas

Las funciones matemáticas sólo calculan resultados a partir de valores pero no "hacen" nada. Algunas funciones de LISP pueded "hacer" algo aparte de la propiacomputación. En otros lenguajes a estas funciones se las denominaprocedimientos, y pueden causar graves trastornos si no se utilizan con precaución. 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 función 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 modificandolaspor 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.

IIIA

TAPIA 2005-2006 54

Ordenación

o Ordenación de secuenciaso 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)

Page 28: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 55

Entrada/salida

La entrada en LISP es muy fácil ya que el lenguaje provee al usuario de un parser completo cuyo nombre es read. Se utiliza para leer y devolver espresionesLISP. 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 devuelvenuna expresión, un carácter y una cadena respectivamente.Para leer de un fichero la función with-open-stream es la más comunmenteutilizada. Asocia un stream a un fichero. Las funciones de lectura tienen un parámetro opcional que es precisamente el nombre de un stream.Las funciones de salida son print que imprime cualquier objeto en una nueva lineadejando un blanco después. prin1 es igual pero sin salto de linea ni blanco. Los formatos generados por estas funciones son leibles por las funciones de entrada.La función más 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)

IIIA

TAPIA 2005-2006 56

> (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))))

Page 29: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 57

Herramientas de depuración

En la mayoria de lenguajes hay dos estrategias de depuración:(1) editar el programa y insertar sentencias de impresión(2) utilizar un programa depurador que altere el estado interno en

tiempo de ejecución.

En LISP hay una tercera que es (3) hacer anotaciones que no son parte del programa pero que automáticamente alteran la ejecución del mismo.

Este es el caso de trace y untrace que ya hemos visto. Otro caso es step. (step expression). Evalua la expresión dando información de cada paso de evaluación.

Otras funciones son: (apropos 'string) Devuelve todos los simbolos que hacen matching con string.(describe 'make-string) Da información sobre el símbolo.(documentation 'first 'function) devuelve la cadena de documentación de la funciónfirst.Si se quiere mirar y tal vez modificar los componentes de una estructura, la herramienta es inspect.

IIIA

TAPIA 2005-2006 58

Valores múltiples

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 .1Hay dos valores después de la flecha porque round devuelve el entero y el resto. La mayoria de las veces los valores múltiples son ignorados y sólo se considera el primero de ellos. (* 2 (round 5.1)) 10Si 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

También se pueden construir funciones que devuelvan múltiples valores.(values 1 2 3) 1 2 3

Page 30: INTRODUCCIÓN AL LENGUAGE COMMON LISP › ~puyol › TAPIA › transpas › Lisp2005.pdf · LISP IIIA TAPIA 2005-2006 2 Introduction. IIIA TAPIA 2005-2006 3 Introducción Bibliografia

IIIA

TAPIA 2005-2006 59

Que hacer para continuar …

Hay varios libros interesantes para aprender técnicas de programación 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 …