Escolar Documentos
Profissional Documentos
Cultura Documentos
Programacin III
Lic. Ricardo Monzn Prof. Adjunto Programacin III Facultad de Ciencias Exactas y Naturales y Agrimensura UNNE
Programacin III
53 55
BIBLIOGRAFIA
65
Common Lisp
Programacin III
INTRODUCCIN Lisp fu propuesto por John McCarthy a finales de los 50. Se diseo como alternativa al modelo de computacin tradicional, es un lenguaje dirigido a procesado simblico en lugar de numrico, implementando el modelo de las funciones recursivas que proporcionan una definicin sintctica y semnticamente clara. Las listas son la base tanto de los programas como de los datos en LISP: es un acrnimo de LISt Processing. Lisp proporciona un conjunto potente de funciones que manipulan listas, implementadas internamente como punteros. Lisp ofrece a los programadores la potencia y generalidad de las estructuras de punteros, librndole de la manipulacin explcita de los mismos y de sus operaciones. LISP fu en sus orgenes un lenguaje simple y pequeo, consistente en funciones de construccin y acceso a listas, definicin de nuevas funciones, unos pocos predicados para detectar igualdades y funciones para evaluar llamadas a funciones. El nico fundamento de control era la recursin y las condicionales simples. Si se necesitaban funciones ms complejas se definan en funcin de las primitivas. A travs de los aos se le han ido incorporando funciones especializadas como estructuras de datos, control del programa, aritmtica de reales y enteros, entrada/salida, edicin de funciones LISP y traceado de la ejecucin de un programa. Estas extensiones han provocado la aparicin de diferentes dialectos del LISP: INTERLISP, MACLISP, FRANZLISP, ZETALISP, etc. Debido a esta proliferacin de dialectos, en 1983, la Agencia de Proyectos Avanzados de Investigacin propuso un dialecto standard del lenguaje conocido bajo el nombre de Common Lisp. En un principio, muchos de los programas desarrollados dentro del mbito de la Inteligencia Artificial se implementaron en LISP. Posteriormente, aparecieron formalismos de ms alto nivel como los sistemas de produccin, sistemas basados en objetos, deduccin de teoremas lgicos, sistemas expertos basados en reglas, etc. utilizando al Lisp como lenguaje para su implementacin. Muchos entornos modernos para la creacin de sistemas expertos estn implementados en Lisp. Pero incluso utilizando estas herramientas, es necesario frecuentemente acceder al Lisp para aumentar la funcionalidad del lenguaje de alto nivel. En algn sentido se podra considerar al Lisp como el "ensamblador" de la Inteligencia Artificial.
Common Lisp
Programacin III
Tema 1
el tipo cons, como una lista. una estructura definida por el usuario. tipos de datos propios del usuario. En cualquier caso, es totalmente dinmico (depende del momento en el que se hace la asignacin). En un lenguaje convencional es necesario declarar el tipo del contenido. En Lisp no es necesario hacerlo, aunque lo permite. Adems un smbolo puede ser el nombre de una funcin cuyo cuerpo estar apuntado por la definicin de funcin. La lista de propiedades dar informacin del smbolo y el package, indica la pertenencia de un determinado smbolo a un package predefinido o de usuario. En un mismo paquete (package) no habr dos smbolos con el mismo nombre. En estos primeros temas haremos referencia exclusivamente a los dos primeros atributos del smbolo. Los dems iremos estudindolos, segn se vea su necesidad, a lo largo del curso.
-2 -2
Un nmero se apunta a s mismo. En general un tomo se apunta a s mismo. Racionales: -2/3, 4/6, 20/2, 5465764576/764 - numerador / denominador. - Notacin: fraccin ::= [signo] {dgito}+ / {dgito}+. Coma flotante: 0.0, -0.5 - Notacin : nmero-coma-flotante ::= [signo] {dgito}* punto-decimal {dgito} Complejos: #C(5 -3), #C(5/3 7.0) = #C(1.66666 7.0), #c(0 1) = n i. - Notacin : #c(a b) Donde a y b, representando la parte real y la parte
2 Apuntes
imaginaria, pueden ser enteros, fracciones o coma flotante. Los caracteres y strings son dos tipos de datos utilizados normalmente para manipular texto. En general, la funcin de evaluacin recae sobre s mismos. Caracteres: #\a, #\A - son objetos que comienzan por: #\ - #\a es evaluado como #\a - #\a en algunas operaciones se trata distinto que #\A Caracteres especiales NO IMPRIMIBLES: #\SPACE, #\NEWLINE Strings: "A", "hola" - Son utilizados a menudo para manipular textos y puede considerarse como series de caracteres o como vectores de caracteres. Un string puede examinarse para determinar qu caracteres lo componen. - Su representacin grfica podra ser:
SIMBOLO NOMBRE IMPRIMIBLE: VALOR: DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
"A" "A"
- La representacin imprimible de un string comienza con " y finaliza por ". Por ejemplo, el string "hola" ser imprimido como "hola". Lo que significa que la evaluacin de un string es el propio string - Otros ejemplos. No slo las letras y en su caso los nmeros pueden formar parte de un string, pueden incluirse diferentes caracteres. Por ejemplo, el string siguiente: "hola adis" - Cuidado!, El carcter #\A no es equivalente al string "A". Los nombres de variables. El atributo valor del smbolo permite que dicho smbolo acte como una variable. Todo nombre de variable debe ser un smbolo atmico. El nombre imprimible del smbolo se usa como el nombre de la variable y el tipo de valor asociado puede ser un tomo o una construccin tipo lista. Los nombres de variables permitidos son: A, CONT, VALOR-FINAL, UNA-LISTA, ENT45 La evaluacin de un smbolo es ms complicada que la de los objetos (enteros, fraccionarios, coma flotante, complejos, caracteres y string) anteriormente vistos. En general, el LISP intentar aplicar la regla de devolver el valor del smbolo. Un ejemplo representado grficamente sera el de un contador con valor 2:
Common Lisp
Tema 1
SIMBOLO CONT NOMBRE IMPRIMIBLE: 2 VALOR: DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
Por su parte la variable VALOR-FINAL puede apuntar a su vez a un smbolo que representa a una variable. Por ejemplo,
SIMBOLO NOMBRE IMPRIMIBLE: VALOR-FINAL VALOR: CONT DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
> VALOR-FINAL CONT Si la variable apunta a una lista Lisp, el valor de la misma depender del contenido de la
lista. Constantes especiales. Existen dos constantes especiales que son smbolos reservados y corresponden con,
T true NIL false o lista vaca () Las constantes especiales apuntan a ellas mismas.
Apuntes
(+ 1 3); " (- 4 6 1); " Todos los programas en Lisp se describen mediante funciones que se definen y llaman con
LISTAS. La estructura utilizada para representar la secuencia de elementos de una lista es la estructura CONS. Cada elemento de una lista se representa a travs de una estructura CONS formada por dos partes, CAR y CDR.
CAR
CDR
El CAR es la primera parte de la estructura y contiene un apuntador al primer elemento de la lista. El CDR es la segunda parte y contiene un apuntador a la siguiente estructura CONS que contiene los siguientes elementos de la lista o si no hay ms elementos un apuntador a NIL. Una lista es unidireccional. Por ejemplo: - El tomo A no es una estructura CONS.
Algunas LISTAS y su representacin con ESTRUCTURAS CONS - () NO TIENE UNA ESTRUCTURA CONS - (A)
A
- (1 2 3)
1
- (A (B C))
Common Lisp
Tema 1
SIMBOLO NOMBRE IMPRIMIBLE: HURACAN-ALICIA VALOR: DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
NIVEL SUPERIOR
En este ejemplo se ve una de las filosofias claras de Lisp, la reutilizacin de cdigo. Es importante no generar continuamente informacin ya existente. Pero de igual modo es necesario tener en cuenta cual es la informacin compartida para evitar efectos no deseados
SIMBOLO NOMBRE IMPRIMIBLE: DIASLABORABLES VALOR: DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
LUN
MAR
MIE
JUE
VIE
SIMBOLO NOMBRE IMPRIMIBLE: VALOR: DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE: DIAS-FUERA
Apuntes
Otra forma de expresar listas es mediante LISTAS PUNTEADAS(dotted list). Cuando el CDR de una estructura CONS apunta a un tomo en lugar de a una estructura CONS o NIL, la lista formada es una lista punteada. Por ejemplo, - Lista (A 4)
- Lista punteada (A . 4)
Las listas punteadas amenudo son llamadas tambin pares punteados. Lisp crea frecuentemente pares punteados (dependiendo de la implementacin) para crear estructuras de datos tipo lista, listas de propiedades y listas de asociacin, que las iremos mostrando (A . (B . (C . nil))) = (A B C) ms adelante. Existen funciones Lisp que permiten crear directamente estas listas. Otros ejemplos en los que se mezclan listas de verdad y listas punteadas pueden ser los siguientes. - ((LAS-LISTAS . PUEDEN) TENER VARIAS ESTRUCTURAS)
TENER
VARIAS
ESTRUCTURAS
LAS-LISTAS
PUEDEN
TENER
VARIAS
ESTRUCTURAS
LAS-LISTAS PUEDEN
Cuando el ltimo elemento de una lista no apunta a NIL, se genera una lista punteada. La ventaja de las listas punteadas es el ahorro de una casilla CONS. Sin embargo, se pierde en flexibilidad ya que el tratamiento de una lista no podr depender de la marca de fin de lista. Adems en una lista , que apunta como ltimo elemento a NIL, permite la modificacin de la
Common Lisp
Tema 1
misma aadiendo nuevas casillas CONS. Sin embargo una lista punteada no permite estas modificaciones ya que se eliminara el ltimo elemento de la lista punteada. Es decir el segundo apuntador de la casilla CONS de la lista punteada quedara modificado por el nuevo valor. Un ejemplo errneo:
(LU MA MI JU VI SEMANA SABADO . DOMINGO FIN-DE-SEMANA)
Esta lista no es sintcticamente correcta. Una lista punteada precisa que despus del punto aparezca un objeto simple y despus un parntesis.
1. 4. EVALUACIN EN LISP
El Lisp Listener es el ciclo que realiza continuamente Lisp, siempre est a la espera de entradas. Cuando recibe una entrada, evala la s-expresin, espera al return, si la forma es atmica o espera a parntesis de cierre si es una lista. Finalmente imprime el resultado y el ciclo comienza de nuevo. A este ciclo se llama ciclo READ-EVAL-PRINT expresado a travs de las funciones Lisp (PRINT (EVAL (READ))). Por tanto, el evaluador es el mecanismo que ejecuta las formas y los programas LISP. Lisp siempre tratar de evaluar todo lo que se le suministre; esto es realizado a travs de la funcin eval; (eval form) se evala la forma y se devuelve el valor. As los nmeros, caracteres y strings tienen reglas de evaluacin simples cuya evaluacin devuelve su propio valor. Ejemplos, si se escribe el 3, Lisp devuelve el 3 si se escribe "esto es un string", Lisp devuelve "esto es un string". Vindolo desde un interprete Lisp, siendo el pront del mismo >: > 3 <return> ;; necesario pulsar return, indicando el final de la s-expresin 3 > esto es un string <return> esto es un string > Podemo decir que qualquier forma que NO es una lista espera un return para poder ser evaluada. >T <return> T > A <return> 5 (si X tiene el valor 5) Cualquier entrada en Lisp tendr una salida imprimible. Por ejemplo, las s-expresiones con quote devuelven siempre su propio valor. > 'A <return>
Apuntes
A > '(+ 2 3) <return> (+ 2 3) > Una forma de lista (sin quote) espera al cierre del parntesis: > (+ 2 3) 5 > (PRINT X) X ;; por la propia funcin de escritura print X ;; resultado de evaluacin de la funcin print > (PRINT "HOLA") HOLA HOLA > (* (+ 2 3) (/ 12 4)) 15 Aunque no es muy usual realizar llamadas explcitas a la funcin eval, se pueden incluso generar diferentes niveles de evaluacin. Por ejemplo, si asumimos los siguientes valores de las variables, X==>Y, Y==>Z, Z==>10, entonces >X Y ; tpico ciclo de evaluacin R-E-P > (EVAL X) Z ; los argumentos son evaluados antes de pasarlos a la funcin. > (EVAL (EVAL X)) 10
Common Lisp
Common Lisp
Programacin III
11
Tema 2
12
Apuntes
CDDR, CADADR, etc. La funcin CAR, devuelve siempre el primer elemento de una lista. Su sintaxis es (CAR LISTA), o de una manera ms tcnica sera, (CAR CONS). Por ejemplo podramos tener la siguiente llamada (CAR (1 2 3)) -==> 1 Sin embargo, esto no funciona, ya que Lisp intentar evaluar la lista (1 2 3). Dar un ERROR. Intentar buscar una funcin definida con el nombre 1 y cuyos argumentos tomen valores 2 y 3 respectivamente. Como ya habamos comentado y para evitar que LISP evale una lista de datos (y en general cualquier objeto) utilizaremos quote/'. As para el ejemplo (CAR '(1 2 3)) - -> 1 anterior tendremos Ms ejemplos de esta funcin sera:
>> (CAR (A B C) ) >> (CAR (A B (C D) E) ) >> (CAR ((A B) C) ) >> (CAR ((A B C)) ) >> (CAR A) >> (CAR ()) / (CAR NIL) Es importante resear que la funcin CAR no resultado la direccin de un elemento que existe.
==> A ==> A ==> (A B) ==> (A B C) ==> ERROR ==> NIL genera un nuevo valor, sino que da como
La funcin CDR, para listas propias, de verdad o no punteadas, devuelve la lista sin el primer elemento. Es decir la funcin CDR devolver los elementos apuntados por el CDR de la primera estructura CONS de una lista (o CONS). Para una lista punteada, el CDR de una estructura CONS puede ser un tomo. Por tanto, en estos casos se devolver un tomo y no una estructura CONS. La sintaxis de esta funcin es (CDR LISTA) o de forma tcnica (CDR CONS).Ejemplos,
>> (CDR (A B C) ) ==> (B C) >> (CDR (A B (C D) E) ) ==> (B (C D) E) >> (CDR ((A B) C) ) ==> (C) >> (CDR ((A)) ) ==> NIL >> (CDR ((A B C)) ) ==> NIL >> (CDR A) ==> ERROR >> (CDR (A . B) ) ==> B El acceso a los elementos de una lista no es directo. Es decir, es necesario acceder a los elementos previos al que se quiere seleccionar.
Las funciones C****R, no son ms que una abreviacin de las formas CAR y CDR. Podemos invocar a las llamadas (C*R LISTA), (C**R LISTA), (C***R LISTA), (C****R LISTA), donde el * podr sustituirse por A, para invocar a CAR, o por D para invocar a
Common Lisp
13
Tema 2
CDR. Los caracteres incluidos invocan a las funciones respectivas en orden de derecha a izquierda.
>> (CADR (A B C) ) (CAR (CDR (A B C) ) ) ==> B >> (CDAR ((A B C) D E) ) (CDR (CAR A B C) ) ) ==> (B C) >> (CADDR (A B C D E) ) ==> C >> (CAR (CDDDDR (A B C D E) ) ) ==> E Sin la funcin CAR, este ltimo ejemplo hubiera devuelto (E). En general no es conveniente hacer uso de estas funciones ya que no son muy clarificadoras. Por ello es mejor utilizar funciones especficas.
Existe una serie de funciones equivalentes a la combinacin de las funciones CAR y CDR. (FIRST LISTA) (CAR LISTA) (SECOND LISTA) (CADR LISTA) (THIRD LISTA) (CADDR LISTA) (FOURTH LISTA) ETC. (TENTH LISTA) Estas funciones slo admitirn un argumento que ser una lista. Normalmente los ndices de las posiciones de los elementos empiezan del 0. LAST LIST. Esta funcin devolver la ltima estructura CONS de la lista. Por ejemplo,
>> (LAST (A B C)) >> (LAST (A (B C))) >> (LAST (1 2 3.5)) >> (LAST ())
==>
((B C))
==>
((A B C))
14
Apuntes
==>
(B . C)
- ELT SECUENCIA INDICE. Esta funcin devolver el elemento de la secuencia que est en la posicin ndice. El primer elemento de la secuencia tiene el ndice en la posicin 0. Ejemplos,
>> (ELT (A (B C)) 1) ==> >> (ELT (A B) 3) ==> >> (SETQ ESTA-LISTA (A B C D E)) >> (ELT ESTA-LISTA 2) ==>
(B C) NIL ==> C (A B C D E)
>> (CONS A (B C D) ) >> (CONS (X Y) (B C D) ) >> (CONS ((X Y) (W Z)) ((A B)) ) >> (CONS A NIL ) >> (CONS NIL (A) )
Common Lisp
15
Tema 2
(A . B) ((A B) . C) (NIL . A)
LIST &REST ARGS La notacin &REST ARG implica que se permite cualquier nmero de argumentos. Es decir, se le puede pasar a la llamada de la funcin cualquier nmero de parmetros. La funcin LIST devuelve una lista formada con todos los elementos pasados como argumentos. Los argumentos debern ser expresiones simblicas, o s-expresiones vlidas. La sintaxis corresponder con llamadas del estilo (LIST SEXP SEXP ...). Algunos ejemplos,
>> s ==> (A B C) >> (LIST (A) (B) (C)) ==> ((A) (B) (C)) >> (LIST A (B C)) ==> (A (B C)) >> (LIST QUIERO (Y PUEDO) CREAR ((ALGUNA LISTA)) DIVERTIDA)
==> (QUIERO (Y PUEDO) CREAR ((ALGUNA LISTA)) DIVERTIDA)
>> (LIST (LIST (LIST A))) ==> (((A))) Como se ha podido observar Lisp construye nuevos datos pero slo en un nivel, el nivel superior.
APPEND &REST ARGS La funcin APPEND concatena los argumentos en una lista. Todos los argumentos, excepto el ltimo deben ser listas. Los argumentos que no sean listas no sern incluidos. Hablando tcnicamente, las casillas CONS de todos excepto el ltimo son copiados en el orden que preserve el orden de los argumentos. As en estas copias, el CDR de la ltima casilla de cada uno de los argumentos se enlaza con el siguiente. Sintcticamente lo indicaramos como (APPEND LISTA LISTA LISTA SEXP). Ejemplos,
>> (APPEND (A) (B) (C)) ==> (A B C) >> (APPEND (A) (B C)) ==> (A B C) >> (APPEND ((A)) ((B)) ((C)) ) ==> ((A) (B) (C)) >> (APPEND (PODRA) ((CREAR (UNA))) () (LISTA)) ==> (PODRA (CREAR (UNA)) LISTA) Quizs otros ejemplos ms interesantes son, >> (APPEND (APPEND (APPEND (A) ))) ==> (A) >> (APPEND (A) NIL) ==> (A) >> (APPEND NIL (B C)) ==> (B C) NIL es una lista y por tanto cumple los requerimientos de la definicin de APPEND. >> (APPEND (A) (B) C) ==> (A B . C) si el ltimo elemento no es una lista se obtiene una lista punteada. >> (APPEND A (B C)) ==> ERROR
16
Apuntes
si el primer argumento es un tomo distinto de NIL, entonces se produce un ERROR. Para ver ms claro el funcionamiento de la funcin append veremos algunos ejemplos grficamente.
===>(A B C)
C
SALIDA
copiados
==> (A)
==> (A B . C)
C
SALIDA
copiados
FUNCIONES DESTRUCTIVAS Las funciones presentadas hasta el momento, manipulan los valores dados como parmetros para obtener un valor. Los smbolos que representan dichos parmetros no son modificados, sin embargo existen otras funciones llamadas destructivas que modifican el contenido de algn parmetro. Por ejemplo:
(RPLACA lista elem), sustituye la cabeza de la lista con elem (setf (car lista) elem) Ejemplos: >> (setq a '(1 2 3)) << (1 2 3) >> (rplaca a 7) << (7 2 3)
->
Common Lisp
17
Tema 2
1 7
(RPLACD lista elem), sustituye el resto de la lista con elem. Ejemplos: >> a << (7 2 3) > (rplacd a '(9)) << (7 9) >> a << (7 9) >> (rplacd a 6) << (7.6) >> a << (7.6) Grficamente podramos verlo como sigue:
A (1) (3) 7 6 (2) 2 3
;(1) ;(2)
;(3)
(NCONC lista1 ... listan), a diferencia de APPEND, NCONC devuelve su valor -> modificando el smbolo que expresa lista1 (setq lista1 (APPEND lista1... listan)). Ejemplos: >> (setq a '(1 2 3)) << (1 2 3) >> (setq b '(4 5 6))
18
Apuntes
2 4
(PUSH item lista), aade un elemento a lista -> (setq lista (cons item lista)). Ejemplos: >> (push 9 b) << (9 4 5 6) >> b << (9 4 5 6)
B
(POP lista), elimina el primer elemento de lista -> (setq lista (cdr lista)). >> (pop b) << 9 >> b << (4 5 6)
Common Lisp
19
Tema 2
(NBUTLAST lista &optional n), elimina los n ltimos elementos -> de lista (setq lista (butlast lista n))
Ejemplos, >> (nbutlast b 2) << (4) >> b << (4)
20
Apuntes
3 2 0
MEMBER ITEM LISTA {&KEY {:TEST / :TEST-NOT / :KEY}}. La funcin MIEMBRO busca en el nivel superior de la LISTA un elemento que sea igual, EQL, que el ITEM. Si se encuentra un elemento que cumple esta condicin, la funcin devolver una lista cuyo CAR es el elemento buscado y el CDR es el resto de la lista. Por el contrario si no se encuentra ningn elemento se devolver NIL. Por defecto, el test que se realiza es EQL. Sin embargo, se puede expresar otro tipo de comparacin en la opcin KEY de la lista de parmetros. La opcin :TEST permite realizar comparaciones sucesivas del ITEM con cada uno de los elementos de la lista a travs del operador sealado despus de :TEST, hasta encontrar el primer elemento que cumple dicha condicin, es decir, que de NONIL. La opcin :TEST-NOT es semejante a la anterior, salvo que se detiene al encontrar el primer elemento en cuya evaluacin se obtenga NIL. Finalmente la opcin :KEY hace lo mismo que las anteriores pero aplica la funcin indicada en clave. Veamos algunos ejemplos,
>> (MEMBER (X Y) (A B C (X Y) D)) ==> ; Su valor es NIL por que compara con EQL
Common Lisp
21
MODULO 2
>> (MEMBER (X Y) (A B C (X Y) D) :TEST #EQUAL) ==> ((X Y) D) >> (MEMBER 7 (3 5 7 9) :TEST-NOT #>) ==> (7 9)
22
Apuntes
Common Lisp
Programacin III
23
Tema 3
>> (/ 25.0 10) >> (/ 7) >> (/ 2.0) >> (/ 48 24 (* 2 3)) Las operaciones aritmticas no modifican los Unicamente devuelven un valor.
>> (INCF C 10) ==> 15 >> C ==> 15 >> (INCF C) ==> 16 >> C ==> 16 Mientras que si asumo que el valor de C es 5, y >> (- 1 C) ==> 4 >> C ==> 5 - DECF, decrementa en una cantidad DELTA, una valor PLACE. (DECF PLACE [DELTA]) Por ejemplo, si asumimos que el valor de C es 5, entonces >> (DECF C 10) ==> -5 >> C ==> -5 >> (DECF C) ==> -6 >> C ==> -6 Mientras que si asumo que el valor de C es 5, y >> (+ 1 C) ==> 6 >> C ==> 5 - SQRT, raz cuadrada de un nmero. (SQRT NUMBER) Por ejemplo, >> (SQRT 16) ==> 4 >> (SQRT 2) ==> 1.414 >> (SQRT -4) ==> #c(0 2) - EXPT, exponencial. Calcula el valor de un nmero elevado a otro nmero. Por ejemplo, >> (EXP 2 3) ==> 8
24
Apuntes
==> ==>
1/9 1
>> (< 3 5 4) ==> - MAYOR QUE, secuencia estrictamente decreciente de nmeros. (> NUM NUM ) >> (> 8 5 3) ==>
NIL T
>> (< 8 3 5) ==> NIL - MENOR O IGUAL QUE, secuencia NO estrictamente creciente de nmeros. (<= NUM NUM ) >> (< 5 5 8) ==> T >> (< 9 9 4) ==> NIL - MAYOR O IGUAL QUE, secuencia NO estrictamente decreciente de nmeros. (>= NUM NUM ) >> (>= 9 7 7) ==> T
- MAXIMO - MIN (MAX NUM NUM ) (MIN NUM NUM )
>> (>= 8 9 8) ==> NIL >> (MAX 2 5 3 1)==> >> (MIN 2 5 3 1)==>
5 1
>> (NUMBERP NOMBRE) ==> NIL - ODDP, verifica un argumento, que debe ser entero, y devuelve cierto si el entero es
impar.
Common Lisp
25
Tema 3
(ODDP ENTERO).
==>
>> (ODDP 5.8) ==> ERROR - EVENP, verifica un argumento, que debe ser entero, y devuelve cierto si el entero es
par. (EVENP ENTERO)
>> (EVENP 8)
==>
>> (EVENP NOMBRE) ==> ERROR - ZEROP, verifica un argumento, que debe ser numrico, y devuelve cierto si el nmero es cero. (ZEROP NUMBER) >> (ZEROP 0.0) ==> T >> (ZEROP NOMBRE) ==> ERROR
Las funciones que no son primitivas en Lisp pueden ser escritas por el usuario. Las definiciones de funciones de usuario son el eje de construccin de Lisp. Algunos mdulos ms adelante veremos claramente estas definiciones, sin embargo presentamos un ejemplo de funcin para ir viendo la sintaxis de la misma. Ejemplo de paso de grados farenheit a celsius. Si F es la temperatura en grados farenheit, entonces la temperatura en grados celsius ser: C = 5/9 *(F-32) (defun CONVERSION-F-a-C (F)
(* (/ 5 9) (- F 32))
26
Apuntes
Common Lisp
Programacin III
>> (ATOM UNA) ==> >> (ATOM ()) ==> >> (ATOM "STRING") ==> >> (ATOM NIL) ==> >> (CONSP (UNA LISTA) ) >> (CONSP ()) ==> >> (LISTP NIL) ==> >> (NULL 5) ==>
27
Tema 4
>> (TYPEP (A B) CONS) ==> ___________ >> (NULL (TYPEP 5.2 INTEGER)) ==> ___________ Predicados de igualdad. Los objetos Lisp pueden verificarse a diferentes niveles de igualdad: igualdad numrica- =, igualdad estructural- EQUAL y de identidad representacional- EQL. Para verificar si dos objetos tienen el mismo valor, se usar normalmente el predicado EQUAL, que devolver T o NIL. Tanto EQUAL como EQL, aceptan slo dos argumentos.
- EQUAL X Y. Verifica si los objetos X e Y, son estructuralmente iguales. Es decir, los valores imprimibles de los objetos son iguales. Sintcticamente tendramos que expresarlo (EQUAL SEXPR SEXPR). Ejemplos
>> (EQUAL 5.0 5) >> (EQUAL NIL ()) >> (SETQ A WORD) >> (SETQ B WORD) >> (EQUAL A B) >> (SETQ L (A B C)) >> (EQUAL (A B C) L) >> (SETQ M L) >> (EQUAL L M) >> (SETQ N (A B C)) >> (EQUAL L N) >> (EQUAL L A)
- EQL X Y. La funcin EQL testea si X e Y representan el mismo valor. Esta funcin puede devolver false aunque el valor imprimible de los objetos se igual. Esto sucede cuando los objetos apuntados por variables parecen los mismos pero tienen diferentes posiciones en memoria. Este predicado no conviene utilizarlo con strings, ya que su respuesta no ser fiable. Por el contrario se deber utilizar con variables y nmeros cuando sea preciso conocer si tienen la misma posicin en memoria. Sintcticamente tendramos (EQL SEXPR SEXPR), donde la sexpr se deber evaluar como un nmero o variable.
>> (EQL 5 5) >> (EQL 5 5.0) >> (SETQ A WORD) >> (SETQ B WORD) >> (EQL A B) >> (SETQ L (A B C)) >> (EQL (A B C) L) >> (SETQ M L) >> (EQL L M) >> (SETQ N (A B C))
==> T ==> NIL (NO FIABLE) ==> T (dos variables apuntan al mismo sitio
28
Apuntes
>> (AND T T T (* 2 5)) ==> 10 >> (SETQ X 3) >> (SETQ CONT 0) >> (INCF CONT) >> (AND (<= CONT 10) (NUMBERP X) (* 2 X)) >> (AND (EVENP X) (/ X 2)) ==> NIL
==>
OR {FORM}*. La funcin OR evala sus argumentos en orden. Si cualquiera de los argumentos se evala a NO-NIL, se detiene la evaluacin y se devuelve es valor. Por el contrario si todos los argumentos son NIL, la funcin OR devolver NIL. Sintcticamente (OR SEXPR SEXPR ), est permitido cualquier nmero de argumentos. Ejemplos,
>> (OR NIL NIL (NULL (A B)) (REM 23 13) ) >> (SETQ X 10) >> (OR (< 0 X) (DECF X) ) ==> T >> (SETQ X 10) >> (OR (CONSP X) (ODDP X) (/ X 2)) ==>
==>
10
NOT FORM. La funcin NOT evala un nico argumento. La funcin NOT devuelve T o NIL. Si los argumentos se evalan a NIL, entonces devuelve T, en otro caso NIL. Sintcticamente (NOT SEXPR), est permitido slo un argumento.
Common Lisp
29
Tema 4
Ejemplos,
>> (NOT NIL) ==> T >> (NOT T) ==> NIL >> (NOT (EQUAL A A) ) ==> NIL >> (SETQ X (A B C) ) >> (AND (NOT (NUMBERP X)) (NOT (ATOM X)) "ESTO ES CONS" )
==> "ESTO ES CONS"
30
Apuntes
Common Lisp
Programacin III
Por ejemplo la llamada a la funcin de suma (+ 2 3). La llamada a la funcin es una lista cuyo primer elemento es el nombre de la funcin y el resto formarn los parmetros de dicha funcin. Lisp comprobar que efectivamente el primer elemento de la lista se corresponde con algn funcin predefinida o del usuario. Los argumentos de la llamada a la funcin sern igualmente evaluados antes de pasrselos como informacin a la funcin (este procedimiento se usa siempre en las llamadas a menos que la funcin sea una macro o una forma especial). Si el argumento de una funcin es a su vez otra llamada a funcin, entonces se evala primero la funcin del argumento y el resultado de la misma se pasa a la funcin principal. Por ejemplo:
31
Tema 5
(+ 3 8)
>> (defun RESTO (L) (CDR L) ) ==> PRIMERO >> (RESTO (A B C)) ==> (B C) El prarmetro L de la definicin se corresponde con una variable local, es decir, slo es accesible desde el interior de la funcin. Si hay una variable externa con igual nombre, la L que hace referencia dentro del cuerpo se refiere a la del argumento. Como decamos se permite hacer declaraciones e incluir documentacin en las funciones. Las declaraciones se utilizan para proporcionar informacin extra al sistema. A menudo son mensajes utilizados por el compilador. Las declaraciones tambin pueden aparecer al principio del cuerpo de ciertas formas como en las funciones. Los string de documentacin se utilizan para describir comandos y pueden imprimirse al invocar la funcin de documentacin de la funcin. Ejemplo, >> (defun CUADRADO (x) "Esta funcin devuelve el cuadrado de un nmero" (* x x) ; fin de CUADRADO ) ==> CUADRADO Esta funcin utiliza un string de documentacin y un comentario justo antes del ltimo
32
Apuntes
parntesis de la funcin.
>> (CUADRADO 3) ==> 9 Qu sucede al definir la funcin CUADRADO? - Lisp crea un smbolo CUADRADO - incorpora en la casilla definicin de funcin el valor correspondiente a dicha funcin. Y cmo se evala y activa una funcin? La evaluacin de una funcin, cuando esta se define, consiste en el nombre de la propia funcin. Por ejemplo, al definir en LISP la funcin CUADRADO, devuelve como valor de la misma CUADRADO. >> (defun CUADRADO (x) (* x x) ) ==> CUADRADO Por otro lado, cuando se llama a una funcin con ciertos argumentos, el valor que devuelve dicha funcin se corresponde con la ltima forma ejecutada en el cuerpo de DEFUN. En la funcin CUADRADO, corresponde con la forma (* x x) >> (cuadrado 3) ==> 9 >> (cuadrado 2) ==> 4 >> (cuadrado (cuadrado 3)) ==> 81 >> (cuadrado (+ -4 5 (/ 3 1))) ==> 16 La definicin de una funcin puede incluir tantos argumentos como se estimen necesarios. Por ejemplo: >> (defun SUMA-CUADRADO (x y) (+ (cuadrado x) (cuadrado y)) ) >> (suma-cuadrado 2 3)
Se pueden definir tambin funciones sin parmetros:
==> ==>
SUMA-CUADRADO 13
>> (defun SALUDO () (print "hola a todos") ) ==> >> (saludo) "hola a todos" "hola a todos" La respuesta de LISP al llamar a la funcin SALUDOS, es mediante dos strings que correspondern: El primer string a la accin del comando PRINT, El segundo es el valor devuelto por la funcin saludo. Otro ejemplo para ver claramente este efecto: >> (defun escribe-los-dos (x y) (print x)
Common Lisp 33
SALUDO
==>
Tema 5
(print y) ) ==> >> (escribe-los-dos "hola" "qu tal?") ==> "hola" "qu tal?" "qu tal?"
La definicin general de una funcin con nombre es:
ESCRIBE-LOS-DOS
(defun nomb (p1 ... pn) cuerpo) donde (p1 ... pn) = ( {var}* [ &optional {var / (var [inic]) / (var [inic] [flag])}*] [ &rest var] [ &key {var / (var [inic])}*] [ &aux {var / (var [inic])}*)
Los usos y significados de cada una de estas opciones son las siguientes. &OPTIONAL {VAR / (VAR INIC) / (VAR INIC FLAG)}*. Los parmetros opcionales no precisan necesariamente argumentos en la llamada. Los parmetros que no tienen correspondencia en la llamada se identificarn con NIL o con el valor que se indique en la inicializacin. Las variables flag pueden utilizarse para indicar si un parmetro opcional se ha pasado como argumento en la llamada.
>> (defun ejemplo-opcional (a &optional (b 2 c) (d 3)) (list a b c d) ) ==> ejemplo-opcional >> (ejemplo-opcional 5) ==> (5 2 NIL 3) >> (ejemplo-opcional 5 6) ==> (5 6 T 3) Los elementos dados como valores de inicializacin se evalan. Por ejemplo, cambiando el ltimo parmetro opcional d, >> (defun ejemplo-opcional (a &optional (b 2 c) (d inicial-d)) (list a b c d) ) ==> ejemplo-opcional >> (setq inicial-d 4) ==> 4 >> (ejemplo-opcional 5) ==> (5 2 NIL 4) &REST VAR. Sigue a los parmetros opcionales y slo tiene un parmetro. En la llamada a la funcin primero se identifican los argumentos necesarios y luego los opcionales, cualquier otro argumento se agrupa en una lista que se identifica con VAR. Por tanto VAR se identificar con NIL si no hay ms argumentos. Por ejemplo >> (defun ejemplo-opcional-rest (a &optional (b 2) &rest x)
34
Apuntes
&KEY {VAR / (VAR INIC)}*. La lambda lista de claves son variables especificadas despus de &KEY y se les puede dar valores de inicializacin. La forma de acceder a las claves en las llamadas de la funcin es a travs de los ":" seguidos del nombre de la clave y en su caso de una forma para darle un valor. Cualquier clave a la que no se hace referencia en la llamada se identifica con NIL. >> (defun ejemplo-op-rest-key (a &optional (b 2) &key c (d 2)) (list a b c d) ) ==> ejemplo-op-rest-key >> (ejemplo-op-rest-key 5 6 :c 10) ==> (5 6 10 2 ) >> (ejemplo-op-rest-key 5 6 :d 10) ==> (5 6 nil 10 ) >> (ejemplo-op-rest-key :d 15) ==> (:d 15 nil 2) La combinacin de opciones &key y &rest en la misma definicin de funcin, da problemas con algunas llamadas. Es necesario que aparezcan todas las referencias a las claves de la definicin, siempre y cuando despus existan ms parmetros en la llamada.
&AUX {VAR / (VAR INIC) / (VAR INIC FLAG)}*. No son parmetros de la funcin, y por tanto no se aceptan como argumentos de la llamada a la funcin. La opcin &AUX se utiliza para establecer variables locales de la funcin a las que se puede asignar un valor inicial. Algunos ejemplos de uso de los distintos tipos de parmetros:
>> (defun caso1 (a &optional (b 3) &rest x &key c (d 1)) (list a b c d x) ) ==> CASO1 >> (caso1 1) ==> (1 3 nil 1 nil) >> (caso1 5 'b :c 8) >> (caso1 1 6 :c 7) >> (caso1 1 6 :d 8 :c 9 :d 10) >> (defun caso2 (a b &key c d) (list a b c d) ) >> (caso2 1 2 :c 8) >> (caso2 :a 1 :d 8 :c 5) >> (caso2 :a :b :c :d) ==> ==> ==> ==> CASO2 (1 2 8 NIL) (:a 1 5 8) (:a :b :d NIL) ==> (5 b 8 1 (:c 8)) ==> (1 6 7 1 (:c 7)) ==> (1 6 9 8 (:d 8 :c 9 :d 10))
Funciones especiales sin nombre o lambda expresiones En algunas ocasiones, y lo veremos ms adelante, es deseable crear funciones sin
Common Lisp
35
Tema 5
(lambda (p1 ... pn) cuerpo) Adems, el comportamiento es semejante al de la funcin. Ejemplos, >> ( (lambda (x y) (list x y) (cons (car x) (cdr y)) ('(a b) '(c d)) )
) ==> (a d)
>> (defun dame-numero (obj) (if (numberp obj) "Es un nmero. Dame ms" "Esto no es un nmero") ) >> (dame-numero 4) >> (dame-numero 'a) ==> DAME-NUMERO ==> "Es un nmero. Dame ms" ==> "Esto no es un nmero"
COND {(TEST {FORMA}+) }+. Permite expresar varias condiciones, ejecutndose la primera que se cumple. La forma COND acepta cualquier nmero de listas cuyos elementos son formas. Estas listas estn formadas normalmente por un test seguido de cero o ms formas consecuentes. Estas formas se ejecutaran si y solo si el test devuelve un valor NONIL. La cabeza de las listas se evala secuencialmente hasta encontrar una que devuelva un valor NO-NIL, entonces las formas siguientes a la cabeza de esa lista se evalan y se sale de la forma COND. Si hubiera listas ms adelante cuyas condiciones (cabeza de lista) fueran tambin ciertas stas no se evalan y por tanto tampoco se ejecutan las formas incluidas en el resto. COND devolver el resultado de la ltima forma evaluada de la lista con un test NONIL. Si todos los test devuelven NIL, entonces COND devolver NIL. El ejemplo general para la sintaxis sera: (COND (TEST1 FORMA11 FORMA12 FORMA1N) (TEST2 ) ; no tiene ningn consecuente y se devolver el valor NO-NIL del test (TEST3 FORMA31 FORMA32 FORMA 3M)
36
Apuntes
>> (setq a 4) ==> 4 >> (cond ((numberp a) "Esto es un nmero") (t "Esto no es un nmero") ) ==> "Esto es un nmero. >> (defun mi-funcin (x) (cond ((< x 0) (- x)) ( t x) ) ;fin-cond ) ;fin-mi-funcin ==> mi-funcin >> (defun verificar (x) (cond ((< x 0) (print "NEGATIVO")) ((= x 0) (print "CERO")) ((<= X 10) (print "VALOR EN RANGO")) (T (print "VALOR MUY GRANDE") x) ) ;fin-cond ) ;fin-mi-funcin ==> mi-funcin
WHEN TEST FROMA1 ... FORMAN. Es equivalente a la forma IF sin opcin de incluir la forma else. Ejemplo,
>> (when (equal a 4) (print "cierto")) >> (when (equal a 3) (print "cierto"))
==> ==>
UNLESS TEST FORMA1 ... FORMAN. Esta forma condicional difiere de las vistas hasta ahora en que se evaluarn las formas siempre que el resultado de la evaluacin del test sea NIL. Hasta ahora la evaluacin de las formas asociados a un test estaba condicionada a que stas dieran como resultado un valor NO-NIL. Ejemplos,
>> (unless (equal a 4) (print "cierto")) >> (unless (equal a 3) (print "cierto"))
CASE KEYFORM {(LIST { FORM}+)}+. Permite realizar ciertas acciones cuando una determinada forma tiene ciertos valores, expresados a travs de una lista. Por ejemplo,
>> (setq mes 'may) ==> may >> (case mes ((ene mar may jul ag oct dic) 31) ((ab jun sep nov) 30) (feb (if (zerop (mod ao 4)) 29 28) ) ) ==> 31
TYPECASE KEYFORM {(TYPE {FORMA}+)}+. Permite como en el caso anterior
Common Lisp
37
Tema 5
realizar una serie de acciones siempre que un determinado objeto sea de la clase indicada. Ejemplo,
>> (SETQ X 2) ==> 2 >> (TYPECASE X (string "es un string") (integer "es un entero") (symbol (print '(es un smbolo))) (otherwise (print "operador")(print "desconocido") ) ) ==> "es un entero" "es un entero "
PROGN {((VAR {INIT})/ VAR*)} DECLARACIONES CUERPO). Proporciona una forma de agrupar una serie de expresiones LISP. Cada una corresponde con un forma determinada y sern evaluadas en orden. Esto podra ser til en la utilizacin de la estructura condicional IF, por ejemplo:
a ) (progn
(format t "~% El segundo argumento, ~a es menor que el primero ~a ~%" b a)
b ) )
El valor devuelto por PROGN corresponde al de la ltima forma evaluada. PROG1 y PROG2, devuelven el valor de la primera y segunda forma respectivamente, mientras se evalan el resto de las formas. Si en la declaracin de un PROGN se incluyen variables locales, la asignacin de sus valores se hace en paralelo, al igual que suceda con LET. LISP da la posibilidad de que la asignacin de valores a las variables se realice secuencialmente mediante PROG*
(PROG* ...)
La devolucin de un valor para una forma puede hacerse explcito mediante RETURN.
38
Apuntes
;;; posterior a la de definicin de funcin (cabecera). ;; 2 ";" y un blanco, se utiliza para comentar una lnea de cdigo. En la lnea inmediatamente ;; seguida a esta. ;slo un ; y sin blanco, se utiliza para explicar una lnea de cdigo en la misma lnea.
Ejemplo de un fichero comentado: ;;;; ******************************************************************* ;;;; Fichero: Ejemplo-comentario.lisp ;;;; Fecha-de-creacin: 20/02/2002 ;;;; Modulo: Apuntes de lisp. ;;;; Comentarios: Este fichero ha sido creado con fines didcticos. ;;;; Autores: Los profesores de I.A. 4 ;;;; (c) 2001 (F.I.S.S.) ;;;; ****************************************************************** (defun pareja (x) ;;; Esta funcin devuelve la pareja del personaje que se pasa como valor del ;;; parmetro x. (case x ;; se realiza la seleccin. ((Peter-pan) "Campanilla") ;Campanilla es una chica que vuela. ((Mortadelo) "Filemn") ;Ambos son agentes de la T.I.A. ( t "no tiene pareja") ) ;Fin de seleccin ) ;Fin de la funcin. ;;; Esperamos que haya encontrado su pareja con esta funcin. Si no modifquela ;;; siempre que lo crea necesario. ;;;; Fin del fichero.
Documentacin de una funcin Despus de la cabecera de una funcin (nombre y parmetros), se puede incluir comentarios mediante " comienzo de comentarios y " final de comentario
>> (defun nombre-funcin (p1 ... pn) "Aqu se pone el comentario" cuerpo ) << nombre-funcin Lisp permite acceder a esta documentacin a travs de la funcin DOCUMENTATION
Common Lisp
39
Tema 5
>> (defun simple (tomo numero &key (lista '(c d))) "Esta es una funcin ejemplo" (list tomo numero lista) ) << simple >> (describe 'simple) A SIMBOL NAME: "SIMPLE" DOCUMENTATION: FNS: "ESTA ES UNA FUNCION EJEMPLO" PACKAGE CELL: #PACKAGE USER FUNCTION CELL: (LAMBDA (ATOMO NUMERO &KEY .... ...... >> (documentation 'simple) "ESTA ES UNA FUNCION EJEMPLO"
Tambin es posible aadirle documentacin a las variables utilizando DEFVAR.
>> (defvar *alumnos* '(Jun Blas) "Contiene el nombre de todos los alumnos matriculados en I.A") *alumnos* >> (documentation '*alumnos*) "Contiene el nombre de todos los alumnos matriculados en I.A"
40
Apuntes
Common Lisp
Programacin III
41
Tema 6
tipo, tal y como seran aceptados por un READ -> (PRINT objeto &optional stream) - PRIN1, es una versin de PRINT, imprime un objeto sin salto de lnea ni blanco. Trata los caracteres ESPACE -> (PRIN1 objeto &optional stream) - PPRINT, introduce slo <RT> -> (PPRINT objeto &optional stream) - PRINC, no escribe los objetos por su tipo. No trata los escapes -> (PRINC objeto &optional stream) - FORMAT, aparece como un mecanismo ms generalizado de dar la salida. Se indican directivas que son como variables situadas entre el string y comienzan con ~. Muchas directivas miran el siguiente argumento de la lista del format y lo procesan de acuerdo a sus propias reglas. Su forma es (FORMAT destino control-string &rest argumentos) - destino = nil/ t/ stream. Si se indica el nil, se crear un string con las caractersticas indicadas y ste ser lo que devuelva el format. Si se indica t, ser la salida por defecto y sino ser otro dispositivo indicado en stream. - control-string = contiene el texto a escribir y "directivas" - argumentos = lista con los parmetros para las "directivas" Se usan diferentes directrices para procesar diferentes tipos de datos e incluirlos en el string: ~A - Imprime un objeto cualquiera., ~D - Imprime un nmero en base 10 y ~S Imprime una expresin simblica. Adems se puede utilizar el smbolo @ junto con la directiva ~A, para justificar a la derecha valores numricos. No todas la directrices utilizan argumentos: ~% - Inserta una nueva lnea y ~| - Nueva pgina. Ejemplos,
>> (FORMAT T "STRING DE SALIDA")STRING DE SALIDA ==> NIL >> (SETQ VAR 5) ==> 5 >> (FORMAT T "STRING QUE INCLUYE ~A" VAR)STRING QUE INCLUYE 5 ==> NIL >> (FORMAT NIL "STRING QUE INCLUYE ~A" VAR) ==> STRING QUE INCUYE 5 >> (FORMAT T "ESCRIBE EL ARGUMENTO ~10@A JUSTIFICADO A LA DERECHA CON 10 ESPACIOS." 1000) ____________________________ ________________________________________________________________ ==> ___________________ >> (FORMAT T "~%LA PRIMERA RESPUESTA ES ~5@A ~%Y LA SEGUNDA RESPUESTA ES ~3@A " (* 5 3 2) (/ 3 5))____________________ ________________________________________________________________ ==> ________ - TERPRI realiza un salto de lnea -> (TERPRI &optional stream) Ejemplos de salida: >> (princ "hola") ==> hola "hola"
42
Apuntes
==> "hola" "hola" >> (prin1 "hola") ==> "hola" "hola" >> (format t "hola") ==> hola NIL >> (format nil "hola") ==> "hola" >> (format nil "hola soy ~a, ~a" "yo" "Bonn") ==> "hola soy yo, Bonn" >> (format nil "~a~%~a" 'que? "donde?") ==> "QUE? donde?" >> (format nil "~(~a~)~%~a" 'que? "donde?") ==> "que? donde?" 6.2. STREAMS
Es un tipo de datos que mantiene la informacin sobre el dispositivo (fichero) al que est asociado. Har que las E/S sean independientes del dispositivo. Un stream puede estar conectado a un fichero o a un terminal interactivo. OPEN Esta funcin devuelve un stream. (OPEN nomfich &key :direction :element-type :if-exist :if-does-not-exist) donde nomfich ser un string/ pathname/ stream; :direction permitir sealar si el dispositivo va a ser de lectura-entrada, :input, salida-escritura, :output, o ambos, :io; :element-type a travs de esta opcin podremos indicar el tipo de objetos que tiene el fichero: character la unidad de transaccin es un caracter (pueden utilizarse las funciones read-char y write-char), (mod n) entero no negativo menor que n (pueden utilizarse las funciones readbyte y write-byte en estos ficheros); :if-exist y queremos escribir sobre l entonces tendremos dos opciones o machacar lo que ya existe, :overwrite, o seguir escribiendo desde el final, :append; por ltimo, con la opcin :if-does-not-exist si queremos abrir un fichero que no existe tendremos estas dos opciones o crearlo, :create, o dar un mensaje de error, :error. Algunos predicados con streams seran: - (STREAMP Objeto), dar T si objeto es un stream - (OUTPUT-STREAM-P stream), dar T si stream es de salida. - (INPUT-STREAM-P stream), ser T si stream es de entrada. CLOSE, Cierra un stream, desaparece la ligadura entre el fichero y el stream (en caso de
Common Lisp
43
Tema 6
estar ligado a l) -> (CLOSE stream &key :abort) * Algunos streams estandar *standar-input* *standar-output* *error-output* *terminal-io* Algunas funciones ms que manipulen ficheros. - (RENAME-FILE fichero nuevo-nombre), cambia de nombre un fichero. Si fichero es un nombre de stream, el stream y el fichero a l asociado resultan afectados. - (DELETE-FILE fichero), borra un fichero. Si fichero es un nombre de stream, el stream y el fichero a l asociado resultan afectados. - (FILE-LENGTH stream-de-fichero), devuelve la longitud de un fichero. Si esta no puede ser determinada devolver nil. - (LOAD fichero &key :verbose :print :if-does-not-exist), carga un fichero al interprete Lisp. A partir de ese momento el entorno Lisp contar con los objetos Lisp definidos en ese fichero. Las claves incluidas en la forma LOAD corresponden con: :verbose Si es t permitir al cargar el fichero, sacar un comentario sobre el *standaroutput* indicando las caractersticas del fichero que est siendo cargado. :print Si es t se saca un valor de cada expresin cargada sobre *standar-output*. :if-does-not-exist Si es nil devuelve nil; si es t el error correspondiente en caso de que lo haya.
44
Apuntes
Common Lisp
Programacin III
>> (defun simple (string) string ) ==> SIMPLE >> (simple "vale") ==> "vale" >> string ==> ERROR, UNBOUND VARIABLE Esta variable slo tiene sentido dentro de la funcin simple, no tiene acceso desde fuera y por tanto si pretendemos tener informacin de dicha variable nos dar un ERROR Veamos ahora grficamente un ejemplo de definicin y llamada a una funcin.
45
Tema 7
DEFINICION DE FUNCION
LLAMADA A LA FUNCION
(SETF A 2 B 5 C 3) (SUM3 A B C)
C
Como se observa lo lista de parmetros apunta a los mismos valores que los correspondientes argumentos en la expresin de llamada. Cuando se termina la ejecucin de la funcin se desligan los valores de la lista de parmetros. Las variables de la lista de parmetros no afectan a las variables que se encuentran fuera del procedimiento. Veamos el efecto del ejemplo anterior.
Las variables ligadas, de la lista de argumentos de una funcin, no pueden ser accedidas por otras funciones llamadas en ejecucin desde la misma (a no ser que estos valores se pasen como argumentos de la nueva funcin llamada). Un ejemplo:
>> (defun menos-simple (string) (simple) ) ==> MENOS-SIMPLE >> (defun simple () string ) ==> SIMPLE >> (menos-simple "algo") ==> ERROR, UNBOUND VARIABLE Al hacer una llamada a la funcin MENOS-SIMPLE con un argumento (asignndole el valor "algo") la llamada interna a la funcin SIMPLE me dar un ERROR. Esta es la norma general, sin embargo puede suceder en algunas implementaciones que la funcin interna tenga acceso a las ligaduras de la funcin padre.
46
Apuntes
Y 5 10 Y
>> Y ==> 10 La asignacin que se realiza sobre la variable X no modifica dicha variable ya que se asigna el valor 10 a la evaluacin de la variable X, es decir, a Y.
La funcin SETQ asigna un valor a una variable. Su sintaxis es, (SETQ {VAR FORM}+). La Q de SETQ es un mnemotcnico para la aplicacin de la funcin quote. Los argumentos impares de la funcin no son evaluados. (SETQ VAR FORM VAR FORM ), puede haber un nmero par de argumentos. Las evaluaciones de las formas y las asignaciones (primero se evala y luego se asigna) se realizan secuencialmente, devolviendo el valor de la ltima evaluacin efectuada. Ejemplos,
>> (SETQ X 5) ==> 5 >> (SETQ NOMBRE "MARIA") ==> "MARIA" >> (SETQ FRUTA (CAR (MANZANA PERA ))) ==> MANZANA Los valores de un smbolo pueden cambiarse con las funciones de asignacin setq y setf.
SIMBOLO NOMBRE IMPRIMIBLE: EDAD-BARBARA VALOR: 2 DEFINICION DE FUNCION: LISTA DE PROPIEDADES: PACKAGE:
Common Lisp
47
Tema 7
La funcin SETF, es utilizada como las SETQ para realizar asignacin de valores a variables. Su sintaxis es (SETF {LUGAR FORM}+). SETF utiliza la forma lugar para determinar una localizacin o direccin en la que hay que realizar la asignacin. El lugar queda restringido a variables o alguna forma de funcin aceptable que normalmente evala un lugar al que asignar un valor. Tal y como la haca SETQ, realiza las evaluaciones y asignaciones secuencialmente, devolviendo el valor de la ltima evaluacin realizada. Ejemplos,
>> (SETF NOMBRE "MARIA") ==> "MARIA" >> (SETF X (A B C) ) ==> (A B C) >> (SETF (CAR X) (CAR (1 2 3)) ) ==> 1 >> X ==> (1 B C) 7.3. SENTENCIA LET
Let permite crear variables locales interiores a una funcin. Su forma general consta de dos partes asignacin de variables y cuerpo , y lo podemos expresar: (LET ({VARIABLE}* / {VARIABLE FORMA}*) {DECLARATIONS}* CUERPO La asignacin de variables es una lista de listas donde cada lista consta de un nombre de variable y una forma a evaluar. Cuando un LET es llamado las formas se evalan asignando paralelamente valores a todas las variables. Por su parte el cuerpo del LET es como el cuerpo de un DEFUN. Cualquier valor previo que tuvieran variables con el mismo nombre se guardarn y se restaurarn al finalizar el LET. Las operaciones incluidas en el LET son evaluadas en el entorno del LET. Y por otra parte las variables creadas en el LET son locales (al LET) y por tanto no pueden ser accedidas desde el exterior (tal y como sucede con DEFUN).
>> (LET ((a 3) (b 4)) (+ (sq a) (sq b)) ) ==> 25 Tal y como suceda en la llamada a una funcin, la ejecucin de un LET devuelve el valor de la ltima evaluacin efectuada. >(defun AREA-CIRCULO (dimetro) (LET ((radio (/dimetro 2))) (* radio radio pi) ) ) ==> AREA-CIRCULO >> (area-circulo 4) ==> 12.566370614 Es importante recalcar que la funcin LET asigna valores en paralelo y por tanto una funcin como: >> (defun suma-algo (x) (let (( x (+ x 2)) (y (+ x 1)) ) y)) ==> SUMA-ALGO >> (suma-algo 3) ==> 4 Si lo que queramos es obtener como resultado de esta funcin 6, hay que utilizar la
48 Apuntes
asignacin secuencial de valores mediante LET*, que realiza la asignacin de variables de manera secuencial. Veamos algunos ejemplos ms.
(setf L (1 2 3)) (let ((A (CAR L)) (B (CADR L)) (C (CADDR L)) ) (PRINT (+ A (+ B C))) ) En este ejemplo las variables A, B y C son variables locales al LET. L es una variable libre. Si la sentencia LET estuviera dentro de una funcin sera mejor pasar el valor de L como parmetro para asegurarse el valor deseado. Es mejor asegurar explcitamente las intenciones de actuacin que depender del estado del entorno.
LET vs SET. Los parmetros del LET se ligan slo dentro del cuerpo del LET. Las asignaciones de SET dentro de un parmetro LET no crean ni modifican variables globales. Las asignaciones realizadas por el SET en variables libres crearn o cambiarn valores globales. Veamos algunos ejemplos.
>> (SETF X 5) >> (SETF E 0) >> (SETF TRIPLE 0) >> (LET ((D 2) (E 3) (CUADRUPLE)) (SETF DOBLE (* D X)) (SETF TRIPLE (* E X)) (SETF CUADRUPLE (* 4 X)) ) << 20 >> D << ERROR - UNBOUND VARIABLE
; variable no ligada
>> E << 0 >> DOBLE << 10 >> TRIPLE << 15 >> CUADRUPLE << ERROR - UNBOUND VARIABLE ; Los valores de las variables libres pueden modificarse en la ejecucin del LET (efecto lateral en la ejecucin del LET).
&AUX vs LET. En la definicin de la funcin tenemos la posibilidad de indicar variables auxiliares. (DEFUN NOMBRE ({PARAM}* &AUX {VAR}* / {(VAR INI)}* ) CUERPO). Las variables auxiliares en la lambda lista de definicin de la funcin no aceptan argumentos en la llamada a la misma. La clave &AUX se utiliza para establecer variables locales a la funcin y los valores de inicializacin se realizan secuencialmente (igual que
Common Lisp 49
Tema 7
LET*). Ejemplos,
(defun calculo-fisico (velocidad tiempo &aux distancia) ;; comienzo del cuerpo de la funcin (setf distancia (* velocidad tiempo)) ) ; fin calculo-fisico (defun calculo-fisico (velocidad tiempo &aux (distancia (* velocidad tiempo)) ) ; cuerpo ) ; fin calculo-fisico
OCULTACION. Recordar que cada vez que se llama a una funcin se crea un nuevo ENTORNO, con las ligaduras de la lista de argumentos con los valores de llamada.
>(defun hamlet (frases) (let ((frase (car frases))) (format t " ~a o no ~a ~% " frase frase) (let ((frase (cadr frases))) (format t "Esta es ~a. ~%" frase) ) ) ) ==> HAMLET Qu entorno se incluye en cada uno de los LET?, qu ligaduras existen en cada momento? Si llamamos a la funcin: >> (hamlet '( "ser" "la cuestin")) ==> ser o no ser Esta es la cuestin El entorno de variables que se ha creado para cada let es grficamente el siguiente:
(let ((frase (car frases))) (format t " ~a o no ~a ~% " frase frase) (let ((frase (cadr frases))) (format t "Esta es ~a. ~%" frase) frase = la cuestin frase = ser
Si en un LET, incluido en una DEFUN, se crea una variable con el mismo nombre que alguno de los parmetros de DEFUN, el valor accesible dentro de LET ser el nuevo valor creado. Sin embargo, fuera del entorno del LET pero dentro del de la funcin el valor accedido ser el de la ligadura entre el argumento y el valor de llamada.
>> (defun algo (z) (let ((z 2)) (* z z) ) z) ==> ALGO >> (algo 5) ==> 5
50
Apuntes
>> (defun otra-funcin-mia (n) (declare (special n)) ; declaracin especial, envo de valor (mi-funcin) ) ==> OTRA-FUNCION-MIA >> (DEFUN mi-funcin () (declare (special n)) ; declaracin especial, toma de valor (1+ n) ==> MI-FUNCION Estas declaraciones pueden aparecer slo al comienzo de ciertas formas especiales como DEFUN y LET. Las variables libres se utilizan para comunicar informacin sobre el estado del programa, que puede ser interesante para varias funciones del programa; especialmente cuando no se quieren pasar como argumentos, o si muchas funciones necesitan el valor de dicha variable y sobre todo si necesitan modificarlo. Pero adems existe otra forma de declarar variables especiales para todas las funciones, sin necesidad de declararlas separadamente en cada una de ellas. Son dos las formas de hacerlo, declarndolas en el "nivel superior" del interprete(top level): - DEFVAR y DEFPARAMETER - DEFCONSTANT Esta es la idea de variable global utilizada en otros lenguajes de programacin. La forma sintcticamente correcta de las mismas es la siguiente: (DEFVAR nom-var [valor]), declara una variable global de nombre nom-var accesible desde cualquier parte del programa (desde cualquier funcin). (DEFPARAMETER nom-var [valor]), tiene las mismas caractersticas que DEFVAR, excepto que ser usado como parmetro y no como variable. (DEFCONSTANT nom-var valor), el valor permanecer constante en nom-var, si se intenta cambiar su valor dar error. Ejemplo: >> (defconstant *c* 36) << *c* >> *c* << 36
Common Lisp
51
Tema 7
>> (setf *c* 40) >>Error: *C* has constant value 36 and cannot be changed to 40
52
Apuntes
Common Lisp
Programacin III
(loop (format t "escribe tu nombre, por favor.") (setq nombre (read)) (format t "escribe tu apellido.") (setq apellido (read)) (format t "es correcta la informacin introducida?") (setq s/n (read)) (if (equal s/n s) (return (cons nombre apellido) ) ) ) ;loop
DO ( {PARAM}* / {(PARAM VALOR)}* / {(PARAM VALOR INCRE)}*) (TESTEVALUACION {FORMAS}*) {FORMAS}*. La estructura DO tiene tres partes: lista de parmetros, test de final y cuerpo. La lista de parmetros liga las variables con sus valores iniciales y en cada ciclo se asignan nuevos valores dependiendo del funcin de incremento indicada. En la estructura DO, primero se activa la ligadura de los parmetros y despus se evala el test de final, y si no se cumple se ejecuta el cuerpo. Esta estructura podemos encontrarle semejanza con la de while ... do utilizada en otros lenguajes.
(DO
Tema 9
cuerpo) Ejemplos: >> (defun exponencial (m n) (do ((resultado 1) (exponente n)) ((zerop exponente) resultado) (setq resultado (* m resultado)) (setq exponente (1- exponente)) ) ) ==> EXPONENCIAL >> (defun nueva-exp (m n) (do ((resultado 1 (* m resultado)) (exponente n (1- exponente))) ((zerop exponente) resultado) ) ) ==> NUEVA-EXP >> (defun nuevo-reverse (lista) (do ((l lista (cdr l)) (resultado nil (cons (car l) resultado))) ((null l) resultado) ) ) ==> NUEVO-REVERSE
DO* A diferencia del anterior realiza la asignacin de variables secuencialmente.
>> (defun exponente (m n) (do* ((resultado m (* m resultado)) (exponente n (1- exponente)) (contador (1- exponente) (1- exponente)) ) ;fin-parmetro ((zerop contador) resultado) ) ;fin-do ) ;fin-defun ==> EXPONENTE
DOTIMES permite escribir procedimientos sencillos con iteracin controlada por un contador. Ejecuta el cuerpo un nmero de veces determinado. (DOTIMES (var forma-limite-superior [forma-resultado]) declaraciones cuerpo) Cuando comienza el ciclo se evala la forma lmite superior, produciendo un valor n. Entonces desde el valor 0 incrementndose en uno hasta n-1, se asigna a la variable var. Para cada valor de la variable se ejecuta el cuerpo y al final, la ligadura con la variable se elimina y se ejecuta la forma resultado dando valor al DOTIMES. Si no tiene forma-resultado, su propsito es realizar efectos secundarios. Ejemplo,
(let ((resultado 1)) (dotimes (cuenta n resultado) (setf resultado (* m resultado) ) ) ) ) ==> exponencial-con-times >> (exponencial-con-times 4 3) ==> 256 >> (defun palindromop (l &optional (inicio 0) (fin (length l))) (dotimes (k (floor (- fin inicio) 2) t) (unless (equal (nth (+ inicio k) l) (nth (- fin k) l)) ; salida antes de terminar todos los (return nil) ) ) )
ciclos
>> (dolist (x '(a b c)) (print x) ) A B C NIL >> (defun miembro (n lista) (dolist (l lista 'NO) (if (equal l n) (return 'SI) ) (print l))) >> (miembro 3 '(1 2 3 4 5)) 1 2 SI
==>
MIEMBRO
8.2. FUNCIONES ITERATIVAS PREDEFINIDAS Son prefcisamente en este tipo de funciones predefinidas, donde pueden tener sentido la definicin de funciones sin nombre o lambda expresiones (como prametro). (MAPCAR funcin lista1 ... listan) Va aplicando la funcin a los sucesivos car's de las listas. La funcin debe tener tantos argumentos como lista tiene el mapcar. Devuelve una lista con los resultados de las llamadas a la funcin. Utiliza LIST para construir el resultado. >> (mapcar #+ (7 8 9) (1 2 3)) >> (mapcar #oddp (7 8 9)) ==> (8 10 12) ==> (T NIL T)
Common Lisp
55
Tema 9
(MAPLIST funcin lista1 ... listan) Se aplica a los CDRs sucesivos de las listas. Devuelve una lista con los resultados de las llamadas a la funcin. Utiliza LIST para construir el resultado. >> (maplist #(lambda (x) (cons fuu x)) (a b c)) ==> ((fuu a b c) (fuu b c) (fuu c))
(MAPCAN funcin lista1 ... listan) Acta igual que mapcar pero utiliza la funcin NCONC para combinar los resultados.
>> (mapcan #lambda (x) (and (numberp x) (list x))) (a 1 b 2 c 3 d 4)) ==> (1 2 3 4)
(MAPCON funcin lista1 ... listan) Acta igual que maplist pero utiliza la funcin NCONC para combinar los resultados.
> >(mapcon #lambda (x) (and (numberp x) (list x))) (a 1 b 2 c 3 d 4)) ==> ((1 a 2 b 3 c 4 d) (2 b 3 c 4 d) (3 c 4 d) (4 d))
Otras funciones: MAPC, MAPL. Slo nos interesan por los efectos laterales, ya que no acumulan los resultados tal y como hacen MAPCAR y MAPLIST. Cuadro resumen: Actan sobre el CAR Devuelven el resultado construido con LIST Devuelven el resultado construido con NCONC Interesan por sus efectos laterales Ejemplos: MAPCAR MAPCAN MAPC Actan sobre el CDR MAPLIST MAPCON MAPL
>> (setq x '(1 2 3)) << (1 2 3) >> (mapcar #'(lambda (arg) (print (list arg arg))) x)
56
Apuntes
(1 1) (2 2) (3 3) << ((1 1) (2 2) (3 3)) >> x << (1 2 3) >> (mapc #'(lambda (arg) (print (list arg arg))) x) (1 1) (2 2) (3 3) << (1 2 3) >> x >> (1 2 3) >> (mapcan #'(lambda (arg) (print (list arg arg))) x) (1 1) (2 2) (3 3) << (1 1 2 2 3 3) >> x << (1 2 3) >> (maplist #'(lambda (arg) (print (list arg arg))) x) ((1 2 3) (1 2 3)) ((2 3) (2 3)) ((3) (3)) << (((1 2 3) (1 2 3)) ((2 3) (2 3)) ((3) (3))) >> (mapl #'(lambda (arg) (print (list arg arg))) x) ((1 2 3) (1 2 3)) ((2 3) (2 3)) ((3) (3)) << (1 2 3) >> (mapcon #'(lambda (arg) (print (list arg arg))) x) ((1 2 3) (1 2 3)) ((2 3) (2 3)) ((3) (3)) << ((1 2 3) (1 2 3) (2 3) (2 3) (3) (3))
Common Lisp
57
Tema 9
58
Apuntes
Son difciles de depurar A veces hay que recompilar funciones despus de cambiar una macro. Tienen, al igual que las funciones, tres partes en su definicin: nombre, lista de
argumentos y cuerpo. Ejemplo de macro que suma dos nmeros. Es importante recordar que las macros no
>> (defmacro sq (x) (list '* x x)) << SQ >> (defun sumq (a b) (+ (sq a) (sq b))) << SUMQ >> (sumq 2 3) << 13
Una macro al igual que una funcin puede tener un nmero variable de argumentos y su cdigo es referenciado desde la celda funcin del smbolo. Cuidado! las macros no son
funciones y no pueden usarse con FUNCALL, APPLY o cualquier otra funcin de mapeo. A continuacin se explica paso a paso el proceso de ejecucin de una llamada a una
>> (sq (+ 3 4)) << 49 a) se crea un entorno donde el argumento de la macro es x = (+ 3 4), esto es debido a que no se evalan sus argumentos en la llamada. Sin embargo, si sq hubiese sido una funcin el valor de x sera 7. b) El cuerpo de la macro (list '* x x) se evala en el entorno creado. El resultado de la evaluacin es lo que se denomina expansin de la macro. En nuestro caso concreto sera:
(* (+ 3 4) (+ 3 4)) c) El entorno en el que el cuerpo de la macro ha sido evaluado desaparece. d) una ejecucin normal de Lisp tiene lugar y el resultado que se obtiene es 49. Para saber que forma va a tener una macro cuando se expande se utiliza
MACROEXPAND:
>> (macroexpand '(sq 5)) << (* 5 5) >> (macroexpand '(sq (+ 3 4))) << (* (+ 3 4) (+ 3 4)) Existe un smbolo especial que se utiliza para la definicin de macros y que se denomina Backquote. Este proporciona una forma alternativa para escribir las macros de forma que quedan escritas creando un molde patrn en la forma en la que va a ser expandida la macro. As, nuestra macro sq se podra escribir: >> (defmacro sq (x) `(* ,x ,x))
Common Lisp
59
Tema 9
Todo aquello que esta detrs del backquote (`) no se evala, excepto lo que aparece precedido por una coma. Es decir, que el backquote sera igual que un quote pero que mira en su interior para ver si hay comas y evaluar lo que viene despus de ellas. Otro smbolo especial es la coma seguida por una arroba (,@) que hace que se elimine un nivel de parentizado. Por ejemplo, si queremos definir una macro que sume un nmero desconocido de enteros es muy interesante utilizar este nuevo smbolo:
>> (defmacro sumaent ( &rest lista-enteros) `(+ ,@lista-enteros)) << sumaent >> (macroexpand '(sumaent 1 2 5 6)) << (+ 1 2 5 6)
>> (defvar *listin* ' ((Pepe.212020)(Paco.213003)(Mara.253539))) << ((Pepe.212020)(Paco.213003)(Mara.253539)) Existen diferentes funciones predefinidas de manejo de listas asociativas ASSOC, acceso al primer para clave-datos -> (ASSOC clave a-list) >> (assoc 'Paco *listin*) << (Paco.213003) ACONS, aade un nuevo para punteado a un A-lista (lista de asociacin) (ACONS clave dato a-list)
->
>> (acons 'Marta 214004 *listin*) << ((Marta.214004)(Pepe.212020)(Paco.213003)(Mara.253539)) >> *listin* << ((Pepe.212020)(Paco.213003)(Mara.253539)) Acons no es destructivo, si se quiere cambiar la lista se debe de hacer utilizando setf: >> (setf *listin* (acons 'Marta 214004 *listin*)) << ((Marta.214004)(Pepe.212020)(Paco.213003)(Mara.253539)) >> *listin* << ((Marta.214004)(Pepe.212020)(Paco.213003)(Mara.253539))
REMOVE, se utiliza para eliminar elementos de la lista
60
->
Apuntes
(REMOVE (assoc clave a-list) a-list) Como resulta que no es destructiva deber de utilizarse acompaada de un setf si quiere variarse el valor de la lista:
>> (remove (assoc 'Pepe *listin*) *listin*) << ((Marta.214004)(Paco.213003)(Mara.253539)) >> *listin* << ((Marta.214004)(Pepe.212020)(Paco.213003)(Mara.253539)) >> (setf *listin* (remove (assoc 'Pepe *listin*) *listin*)) << ((Marta.214004)(Paco.213003)(Mara.253539)) >> *listin* << ((Marta.214004)(Paco.213003)(Mara.253539))
RASSOC, permite acceder a la primera clave que tiene asociado un dato concreto, devolviendo el par punteado correspondiente -> (RASSOC item a-list)
>> (rassoc 213003 *listin* :test (function equalp)) << (Paco.213003) Por defecto esta funcin hace una bsqueda utilizando la funcin eql. Un ejemplo de A-lista o lista de asociacin podra ser,
( (NOMBRE . JUAN URRETA) (SEXO . H) (EDAD . 28) (NACIMIENTO . 28 MAYO 1968))
clave dato clave dato clave dato clave Algunos ejemplos de utilizacin de las funciones ASSOC y RASSOC.
dato
>> (ASSOC FRUTA ((ANIMAL . PERRO) (CARNE . FILETE) (FRUTA . MANZANA)) ==> (FRUTA . MANZANA) >> (ASSOC HOBIES ((NOMBRE JUAN URRETA) (EDAD 28) (SEXO H) (HOBIES DORMIR COMER BEBER)) ==> (HOBIES DORMIR COMER BEBER) >> (RASSOC URRETA ((BARBARA . RODRIGUEZ) (RUBEN RODRIGUEZ) (JUAN URRETA) (MAITE URRETA) ) ==> (JUAN . URRETA) Las referencias a funciones en algunas de las primitivas anteriores se expresan formalmente como (FUNTION NOMBRE-FUNCION), y de modo abreviado #'NOMBREFUNCION. Ejemplos, >> #'+ ==> # <puntero a la definicin de la funcin "+"> >> #'EQUAL ==> # <puntero a la definicin de EQUAL> >> #'(LAMBDA (X Y) (+ X Y)) ==> # <puntero a la representacin>
Common Lisp
61
Tema 9
>> (defvar *Juan*) >> (setf (get '*Juan* 'pelo) 'negro (get '*Juan* 'ojos) 'claros (get '*Juan* 'barba) 'si ) << si >> (get '*Juan* 'ojos) << claros >> *Juan* << nil Se puede crear listas de propiedades para un objeto que no est definido.
SYMBOL-PLIST, devolver la lista de propiedades asociada al smbolo.
>> (symbol-plist '*Juan*) << (barba si ojos claros pelo negro) >> (setf (get '*Juan* 'tez) 'morena) << morena >> (symbol-plist '*Juan*) << (tez morena barba si ojos claros pelo negro)
REMPROP, permite borrar una propiedad de una lista de propiedades asociada a un smbolo -> (REMPROP lista-propiedades propiedad). Ejemplos,
>> (remprop '*Juan* 'pelo) << pelo >> (remprop '*Juan* 'aos) << nil >> (symbol-plist '*Juan*) << (tez morena barba si ojos claros) 9.4. ESTRUCTURAS DE REGISTRO
Corresponde con el concepto de registro en Pascal y de estructura en C. DEFSTRUCT, la definicin de una estructura se realiza indicando el nombre para ese tipo de estructura y los campos o registros, donde cada campo puede ser un smbolo (nombre del campo) o una lista con dos elementos, un smbolo (nombre del campo) y un valor
62 Apuntes
(DEFSTRUCT (nombre opcion1 ... opcionn) (campo1 valor-defecto opcion11 ... opcion1m)...) opcioni: (:type list) (:include nom-estructura) opcionij: (:type integer) (:read-only t) La opcin type permite especificar los tipos vlidos para un determinado campo. Readonly no permitir ningn tipo de modificacin sobre ese campo, lo que significa que slo se podr indicar un valor en tiempo de creacin. Una vez definida una estructura, automticamente se definen todas las funciones de creacin y acceso a campos para esa estructura. Un ejemplo, >> (defstruct MANO (nombre " " :TYPE string :READ-ONLY t) ;nombre jugador (cartas () :TYPE list) ;mano en el juego (valor 0 :TYPE integer) ;puntos en mano ) ;fin definicin de la estructura Otro ejemplo para crear la estructura empleado con las siguientes caractersticas es: >> (defstruct empleado nombre departamento puesto ) Automticamente se habrn creado las siguientes funciones de acceso: - ACCESO A LA ESTRUCTURA: make-empleado - ACCESO AL CAMPO: empleado-campoi
La creacin de estructuras, una vez definida una estructura se realizar con la combinacin de SETF y MAKE-nombre-estructura. Por ejemplo,
>> (setf emp1 (make-empleado)) ;; Crea un instancia de empleado llamada emp1. >> (setf emp1 (make-empleado :nombre 'Juan :departamento 'informtica :puesto programador ) ;; Crea una instancia de empleado dando valor a sus campos.
El acceso al valor de un registro se realiza mediante una forma, expresada en una lista cuya cabeza es el nombre de la estructura, un guin, y el nombre del registro al que se quiere acceder y un segundo elemento de la lista que ser el nombre de la estructura concreta a la que quiero acceder. >> (empleado-nombre emp1) << Juan La modificacin de un registro concreto de una estructura se realiza con la combinacin
Common Lisp
63
Tema 9
>> (setf (empleado-nombre emp1) 'Miguel) Ejemplo >> (Defstruct (Directivo (:include empleado)) (Despacho Ala-oeste)) << DIRECTIVO. >> (Setf Luis (make-directivo :nombre Luis :departamento Sistemas :puesto Director :despacho 2Ala-oeste))
64
Apuntes
Common Lisp
Programacin III
BIBLIOGRAFIA
GNU Common Lisp: comunidad, 2007. XLISP-PLUS version 3.04 Help User Guide References. Common Lisp: The language. Guy Steel- Digital Press, 1984. Lisp. Patrick Henry Winston. Berthold Klaus Paul Horn. Addison-Wesley, 1989. Lisp (Tercera Edicin). Patrick Henry Winston. Berthold Klaus Paul Horn. Addison-Wesley
Iberoamericana, 1991.
Lisp Programazio-Lengoaia. J.R. Bastarrica, K. Sarasola. Inprimategia BOAN S.A. 1991. Common Lisp Programming. Education & development center. Texas instruments- data
65