You are on page 1of 17

Cap´ ıtulo 2

Introducci´ on a Lisp

Resumen El objetivo de este cap´ ıtulo es que puedan programar en Lisp tan pronto como sea posible. Al final de la misma, conocer´ an lo suficiente de Lisp como para comenzar a escribir sus propios programas. Este material debe revisarse como un tutorial b´ asico sobre el lenguaje Lisp.

2.1.

Expresiones

Es particularmente cierto que la mejor forma de aprender Lisp es us´ andolo, porque se trata de un lenguaje interactivo. Cualquier sistema Lisp, incluye una interfaz interactiva llamada top-level. Uno escribe expresiones Lisp en el top-level, y el sistema despliega sus valores. El sistema normalmente despliega un indicador (el prompt >) de que est´ a esperando que una expresi´ on sea escrita. Ej. Una de las expresiones Lisp m´ as simples es el entero, si escrib´ ımos el entero 1 despu´ es del prompt y tecleamos enter, tenemos:
> 1 1 >

el sistema despliega el valor de la expresi´ on, seguida de un nuevo prompt, indicando que est´ a listo para evaluar una nueva expresi´ on. En este caso, el sistema despleg´ o lo mismo que tecleamos porque los n´ umeros eval´ uan a si mismos. Las cosas son m´ as interesantes cuando una expresi´ on necesita algo de trabajo para ser evaluado. Ej. Sumar dos n´ umeros:
> (+ 2 3) 5 >

En la expresi´ on (+ 2 3) el + es llamado el operador y los n´ umeros 3 y 4 son sus argumentos. Como el operador viene al principio de la expresi´ on, esta notaci´ on
17

4 2) es evaluado. Lisp eval´ ua el primer argumento de izquierda a derecha (. o bien es una lista que consiste de cero o m´ as expresiones delimitadas por par´ entesis. es necesario utilizar los par´ entesis para indicar donde inicia y donde termina una expresi´ on. 2. esto es todo lo que hay que decir sobre la notaci´ on en Lisp. ser´ a evaluado con las mismas reglas. los valores de los argumentos son 2 y 3. si queremos sumar tres n´ umeros en notaci´ on “normal”. veremos que es uno de los mejores aspectos de Lisp. 2.2. Los valores de los argumentos son pasados a la funci´ on nombrada por el operador. . Ej. Est´ etica minimalista. Si alguno de los argumentos es a su vez una llamada de funci´ on. Las expresiones pueden anidarse. + es una funci´ on y (+ 2 3) es una llamada a la funci´ on. Estos valores son pasados a la funci´ on .7 1)(. Estos valores son pasados a la funci´ on .4 2)) pasa lo siguiente. Ej. En Lisp. esto es. dividido por cuatro menos dos. Como veremos. Ej.4 2)) 3 En espa˜ nol esto corresponde a siete menos uno.7 1) (. En este caso la funci´ on + que regresa 5. 1. lo hace en dos pasos: 1. Evaluaci´ on Veamos m´ as en detalle como las expresiones son evaluadas para desplegar su valor en el top-level. Los argumentos de la llamada son evaluados de izquierda a derecha. como 1. En Lisp s´ olo necesitamos agregar otro argumento. respectivamente. El siguiente argumento (. necesitar´ ıamos usar dos veces el operador +: 2+3+4. 2. 4 es evaluado como 4 y 2 como 2.que regresa 2. En este caso. > (/ (. el argumento de una expresi´ on puede ser otra expresi´ on compleja.18 2 Introducci´ on a Lisp se conoce como prefija y aunque parezca extra˜ na al principio. Por ejemplo.que regresa 6. Toda expresi´ on Lisp es un a ´ tomo. Las siguientes sumas son v´ alidas en Lisp: > (+) 0 > (+ 2) 2 > (+ 2 3) 5 > (+ 2 3 5) 10 Como los operadores pueden tomar un n´ umero variable de argumentos. Al evaluar la expresi´ on (/ (.7 1). Cuando Lisp eval´ ua una llamada a alguna funci´ on. 7 es evaluado como 7 y 1 como 1. c´ odigo y datos usan esta notaci´ on en Lisp.

evaluada. Ej. Ej.. No todos los operadores en Lisp son funciones. Un tipo de datos que ya usamos es el entero. > ’(Mis 2 "ciudades") (MIS 2 "CIUDADES") > ’(La lista (a b c) tiene 3 elementos) (LA LISTA (A B C) TIENE 3 ELEMENTOS) Observen que un s´ olo quote protege a toda la expresi´ on. Otro tipo de datos es la cadena de caracteres que se delimita por comillas. Los operadores que no siguen la regla de evaluaci´ on se conocen como operadores especiales. . Ej. Se puede construir listas usando el operador list que es una funci´ on. Ej. pos ora”. que se escribe como una secuencia de d´ ıgitos. pero la mayor´ ıa lo son. que se conoce como regla de evaluaci´ on de Lisp. Todas las llamadas a funci´ on son evaluadas de esta forma. y por lo tanto. Datos Lisp ofrece los tipos de datos que podemos encontrar en otros lenguajes de programaci´ on y otros que no. Normalmente se evaluan como si estuvieran escritos en may´ usculas. Los elementos pueden ser de cualquier tipo. como en ejemplo anterior. incluidas las listas. independientemente de como fueron tecleados. En la siguiente secci´ on veremos porque esta protecci´ on puede ser u 2. despliega lo que el usuario tecleo.2. as´ ı que si es necesario referirse a ellos. Se debe usar quote con las listas. > ’Amarone AMARONE Los s´ ımbolos por lo general no evaluan a si mismos. Ej. Enteros y cadenas eval´ uan a ellos mismos. sus argumentos son evaluados. verbatim.3. Dos tipos de datos propios de Lisp son los s´ ımbolos y las listas. La regla de evaluaci´ on de quote es –No hagas nada. Las listas se representan como cero o m´ as elementos entre par´ entesis.3 Datos 19 3. > (quote (+ 2 3)) (+ 2 3) > ’(+ 2 3) (+ 2 3) Lisp provee el operador quote como una forma de evitar que una expresi´ on sea ´ til. incluidas las expresiones en ella. Los valores 6 y 2 son pasados a la funci´ on / que regresa 3. “ora et labora. Ej. Un operador Lisp que no sigue la regla de evaluaci´ on es quote (se abrevia ’). se debe usar quote. ya que de otra forma Lisp las tomar´ ıa como una llamada a funci´ on. Los s´ ımbolos son palabras. 256.

en otro caso.4. observen que los programas Lisp se representan como listas. Si el argumento est´ etico no bastar´ a para defender la notaci´ on de Lisp. > () NIL > NIL NIL 2. Si una lista es precedida por el operador quote. . Ej. > (car ’(a b c)) A > (cdr ’(a b c)) (B C) Se pueden usar combinaciones de car y cdr para accesar cualquier elemento de la lista. como un par de par´ entesis o con el s´ ımbolo NIL. Ej.20 2 Introducci´ on a Lisp > (list ’mis (+ 4 2) "colegas") (MIS 6 COLEGAS) Est´ etica minimalista y pragm´ atica. regresa una nueva lista con el primer argumento agregado en el frente. > (cons ’a ’(b c d)) (A B C D) > (cons ’a (cons ’b nil)) (A B) El segundo ejemplo es equivalente a: (A B) Las funciones primitivas para accesar los elementos de una lista son car y cdr. Si su segundo argumento es una lista. Ej. Ej. la evaluaci´ on regresa la misma lista. la lista es evaluada como si fuese c´ odigo. Ej. > (list ’(+ 2 3) (+ 2 3)) ((+ 2 3) 5) En Lisp hay dos formas de representar la lista vacia. Operaciones con listas La funci´ on cons construye listas. esto debe bastar –Un programa Lisp puede generar c´ odigo Lisp! Por eso es necesario quote. El car de una lista es su primer elemento (el m´ as a la izquierda) y el cdr es el resto de la lista (menos el primer elemento).

5 Valores de verdad 21 > (car (cdr (cdr ’(a b c d)))) C > (caddr ’(a b c d)) C > (third ’(a b c d)) C 2. Ej. .2. > (if (listp ’(a b c d)) (+ 1 2) (+ 3 4)) 3 > (if (listp 34) (+ 1 2) (+ 3 4)) 7 Como quote. La expresi´ on test es evaluada. La representaci´ on por default de falso es nil. y la idea al usar if es que s´ olo uno de sus argumentos sea evaluado.5. Si bien el default para representar verdadero es t. Ej. No puede implementarse como una funci´ on. si su valor es falso. el s´ ımbolo t es la representaci´ on por default para verdadero. if es un operador especial. la expresi´ on then es evaluada. las funciones null (lista vac´ ıa) y not (negaci´ on) hacen exactamente lo mismo: > (null nil) T > (not nil) T El condicional (estructura de control) m´ as simple en Lisp es if. Ambos evaluan a si mismos. Ej. si su valor es verdadero. todo excepto nil cuenta como verdadero en un contexto l´ ogico. la expresi´ on else es evaluada. La funci´ on listp regresa verdadero si su argumento es una lista: > (listp ’(a b c)) T > (listp 34) NIL Una funci´ on cuyo valor de regreseo se int´ erpreta como un valor de verdad (verdadero o falso) se conoce como predicado. porque los argumentos de una funci´ on siempre se evaluan. Valores de verdad En Lisp. En lisp es com´ un que el s´ ımbolo de un predicado termine en p. Normalmente toma tres argumentos: una expresi´ on test. Como nil juega dos roles en Lisp. una expresi´ on then y una expresi´ on else.

Un s´ ımbolo usado de esta forma se conoce como variable. en este caso definidos como macros. or se detiene en cuanto encuentra un elemento verdadero. El segundo argumento (lst) indica que la funci´ on tiene un s´ olo argumento. As´ ı definir´ ıamos third: > (defun tercero (lst) (caddr lst)) TERCERO El primer argumento de defun indica que el nombre de nuestra funci´ on definida ser´ a tercero. se calcular´ a el primer elemento. del resto.6. es m´ as sencillo entender lo que es un s´ ımbolo. Los s´ ımbolos son nombres de variables. Ej. en este caso. Funciones Es posible definir nuevas funciones con defun que toma normalmente tres argumentos: un nombre. De manera similar. Ej. Si todos los argumentos son verdaderos (diferentes de nil). 2. Ambos toman cualquier n´ umero de argumentos. que existen con derechos . Ej. del resto del par´ ametro (caddr lst). Cuando la variable representa el argumento de una funci´ on.22 2 Introducci´ on a Lisp > (if 27 1 2) 1 > (if nil 1 2) 2 Los operadores l´ ogicos and y or parecen condicionales. El resto de la definici´ on indica lo que se debe hacer para calcular el valor de la funci´ on. lst. entonces and ´ ltimo argumento. > (or nil nil (+ 1 2) nil) 3 Observen que los operadores l´ ogicos son operadores especiales. ninguno de los argumentos posteriores es evaluado y el operador regresa nil. una lista de par´ ametros y una o m´ as expresiones que conforman el cuerpo de la funci´ on. regresa el valor del u > (and t (+ 1 2)) 3 Pero si uno de los argumentos de and resulta falso. pero solo evaluan los necesarios para decidir que valor regresar. > (tercero ’(a b c d e)) C Ahora que hemos introducido el concepto de variable. para cualquier lst. se conoce como par´ ametro.

Ej. pieza por pieza. podemos definir una funci´ on que verifica si la suma de sus dos primeros argumentos es mayor que el tercero: > (defun suma-mayor-que (x y z) (> (+ x y) z)) SUMA-MAYOR-QUE > (suma-mayor-que 1 4 3) T Lisp no distigue entre programa. Una funci´ on que se llama a si misma se conoce como recursiva. pero cualquier funci´ on puede ser llamada desde el top-level. suma-mayor-que llama a las funciones + y >. Ej. Por ello s´ ımbolos y listas deben protegerse con quote para ser accesados.7 Recursividad 23 propios en el lenguaje Lisp. conforme los vamos escribiendo. Una funci´ on puede llamar a cualquier otra funci´ on. La llamada a miembro es como sigue: . incluida ella misma. procedimiento y funci´ on. Ej. esto significa que posible probar nuestros programas. Recursividad Las funciones que hemos definido hasta ahora. Entre otras cosas. todos cuentan como funciones y de hecho. Si se desea considerar una funci´ on en part´ ıcular como main. casi todo el lenguaje est´ a compuesto de funciones. He aqu´ ı una versi´ on recursiva simplificada de esta funci´ on: > (defun miembro (obj lst) (if (null lst) nil (if (eql (car lst) obj) lst (miembro obj (cdr lst))))) MIEMBRO El predicado eql verifica si sus dos argumentos son id´ enticos. llaman a otras funciones para hacer una parte de sus c´ alculos. el resto lo hemos visto previamente. En Lisp la funci´ on member verifica cuando algo es miembro de una lista. Podr´ ıamos decir que la definici´ on de una funci´ on corresponde a la versi´ on generalizada de una expresi´ on Lisp. lo que se conoce como programaci´ on incremental (bottom-up).7.2. La siguiente expresi´ on verifica si la suma de 1 y 4 es mayor que 3: > (> (+ 1 4) 3) T Substituyendo los n´ umeros part´ ıculares por variables. un s´ ımbolo debe protegerse porque de otra forma es procesado como si fuese una variable. Una lista debe protegerse porque de otra forma es procesada como si fuese c´ odigo. 2. es posible hacerlo.

Parte del trabajo se da por encargo a otras funciones y el resultado final se empaqueta y se expide como el valor de la funci´ on. 2. De esta forma. En gran medida esto se debe a que usamos la met´ afora equivocada de funci´ on. siempre ayuda a entenderla.8. o M-x lisp-mode en Emacs. Por ejemplo. verificar si la lista lst est´ a vac´ ıa. donde las materias primas llegan como par´ ametros. examinarlos. El proceso que el historiador utilizar´ ıa para examinar un documento es el siguiente: 1. De otra forma. Buscar en e on relativa a cambios de poblaci´ on en Europa. en cuyo caso es evidente que obj no es un miembro de lst. Si el documento menciona otros documentos que puede ser u Piensen en miembro como las reglas que definen cuando algo es miembro de una lista y no como una m´ aquina que computa si algo es miembro de una lista. Traducir una funci´ on recursiva a una descripci´ on como la anterior. 2. ´ nicamente si es miembro del resto de 3.24 > (miembro ’b ’(a b c)) (B C) > (miembro ’z ’(a b c)) NIL 2 Introducci´ on a Lisp La descripci´ on en espa˜ nol de lo que hace la funci´ on miembro es como sigue: 1. si obj es el primer elemento de lst entonces es miembro de la lista. Casi todo editor puede configurarse para verificar par´ entesis bien balanceados. la paradoja desaparece. Primero. Ej. obj es miembro de lst u lst. Tenemos la tendencia de pensar en una funci´ on como cierta forma de m´ aquina. Cualquier hacker en Lisp tendr´ ıa problemas para leer algo como: > (defun miembro (obj lst) (if (null lst) nil (if . es com´ un toparse con dificultades para entender la recursividad. Solemos usar procesos recursivos en nuestras actividades diarias. ´ tiles. De otra forma. Al principio. 3. supongan a un historiador interesado en los cambios de poblaci´ on a trav´ es de la historia de Europa. un programador en realidad usa los margenes en el c´ odigo para hacerlo m´ as legible. :set sm en el editor vi. Obtener una copia del documento que le interesa. ´ l la informaci´ 2. Si bien los par´ entesis delimitan las expresiones en Lisp. Si se usa esta met´ afora la recursividad resulta parad´ ojica – ¿Qu´ e sentido tiene darse por encargo trabajo cuando uno ya est´ a ocupado? Una met´ afora m´ as adecuada es ver a las funciones como procesos que vamos resolviendo. Leyendo y escribiendo Lisp Est´ etica.

cada A reserva espacio para insertar un objeto y el % indica un salto del´ ınea. Los espacios reservados de esta forma. por ejemplo.2. en lisp: CLIM. Dentro de esta cadena. De otra forma el sistema dar´ a la impresi´ on de haberse plantado. generalmente el top-level. el segundo es una cadena que se usa como molde (template). La funci´ on de salida m´ as general en Lisp es format. 1 De hecho. indica que la salida ser´ a desplegada en el dispositivo est´ andar de salida. sino dentro de alguna funci´ on. ˜ %" 2 3 (+ 2 3)) 2 MAS 3 IGUAL A 5. El segundo argumento es una cadena que sirve como molde de lo que ser´ a impreso. Esta funci´ on toma dos o m´ as argumentos: el primero indica donde debe imprimirse la salida. por lo que el valor que regresa queda generalmente oculto. no es recomendable usar read sin desplegar antes un mensaje que solicite la informaci´ on al usuario. Ej. Una funci´ on que despliega un mensaje y lee la respuesta el usuario: > (defun pregunta (string) (format t "˜A" string) (read)) PREGUNTA > (pregunta "Su edad: ") Su edad: 34 34 Puesto que read espera indefinidamente a que el usuario escriba algo. Entradas y salidas Hasta el momento hemos procesado las E/S impl´ ıcitamente. Common Graphics. Sin argumentos. Ej. normalmente la lectura se hace a partir del top-level. NIL Observen que dos l´ ıneas fueron desplegadas en el ejemplo anterior. > (format t "˜A mas ˜A igual a ˜A. utilizando el toplevel.9. t. Normalmente no llamamos a format en el top-level. . y el resto son generalmente objetos cuya representaci´ on impresa ser´ a insertada en la cadena molde. desplegada por el top-level como se hace con toda funci´ on.9 Entradas y salidas (eql (car lst) obj) lst (miembro obj (cdr lst))))) MIEMBRO 25 2. La primera es producida por format y la segunda es el valor devuelto por la llamada a format. La funci´ on est´ andar de entrada es read. El primer argumento de format. son ocupados por el resto de los argumentos en el orden en que son evaluados. etc. casi todo el software actual incluye alguna interfaz gr´ afica con un sistema de ventaneo. Para programas interactivos esto no es suficiente1 . as´ ı que veremos algunas operaciones b´ asicas de E/S.

Cada variable es inicializada con el valor que regrese la expresi´ on asociada a ella. escriba un numero: ") (let ((val (read))) (if (numberp val) val (preguntar-num)))) Esta funci´ on crea la variable local var para guardar el valor que regresa read. Esas variables son v´ alidas dentro del cuerpo de let. que permite la creaci´ on de nuevas variables locales. El cuerpo de una funci´ on puede incluir cualquier n´ umero de expresiones. Hasta el momento. con los valores 1 y 2 respectivamente. el sistema imprime algo. Como este valor puede ahora ser manipulado por Lisp. es un aut´ entico parser de Lisp que evalua su entrada y regresa los objetos que se hallan generado. En el ejemplo. x e y. las expresiones ´ ltima en su cuerpo son evaluadas en orden y la funci´ on regresar´ a el valor de la u expresi´ on evaluada. Cuando la funci´ on es llamada. no hay efectos colaterales. Ej. Pero al usar format. cada una de ellas con la forma (variable expresi´ on). Cuando se escribe c´ odigo sin efectos colaterales. Lisp sin efectos colaterales. 2. esto es un tipo de efecto colateral. Un efecto colateral es un cambio en el sistema Lisp producto de la evaluaci´ on de una expresi´ on. La u on evaluada en el cuerpo producir´ a el valor de la funci´ on. viene el cuerpo de let constituido por una serie de expresiones que son evaluadas en orden. Presento ahora como ejemplo una funci´ on preguntar m´ as selectiva: > (defun preguntar-num () (format t "Por favor. no hay raz´ on alguna para definir ´ ltima expresi´ funciones cuyo cuerpo incluye m´ as de una expresi´ on.26 2 Introducci´ on a Lisp Se debe mencionar que read hace mucho m´ as que leer caracteres. adem´ as de obtener el valor nil. la funci´ on revisa que se ha . pero el valor de las expresiones evaluadas antes se perder´ a. esto es. el sistema simplemente regresa el valor 5. Cuando evaluamos (+ 2 3). Variables Uno de los operadores m´ as comunes en Lisp es let. aunque corta. lo que hemos mostrado se conoce como Lisp puro. > (let ((x 1)(y 2)) (+ x y)) 3 Una expresi´ on let tiene dos partes: Primero viene una lista de expresiones definiendo las nuevas variables locales. Despu´ es de la lista de variables y valores. muestra algo que no hab´ ıamos visto antes: su cuerpo incluye m´ as de una expresi´ on Lisp. s´ olo hay una llamada a +. La funci´ on pregunta. En el ejemplo anterior se han creado dos variables.10.

escriba un numero: a Por favor. Asignaciones En Lisp el operador de asignaci´ on m´ as com´ un es setf.2. pero por el momento no es necesario entrar en detalles . escriba un numero: (un numero) Por favor. se usa la convenci´ on de nombrar a las variables globales con s´ ımbolos que inicien y terminen en asterisco. Para verificar si un s´ ımbolo es el nombre de una variable global o constante. Se pueden definir tambi´ en constantes globales usando defconstant: > (defconstant limit (+ *glob* 1)) No hay necesidad de dar a las constantes nombres distintivos porque si se intenta usar el nombre de una constante para una variable se produce un error. Ej. escriba un numero: 3 3 Las variables de este estilo se conocen como locales porque s´ olo son v´ alidas en cierto contexto.11 Asignaciones 27 escrito para decidir que hacer. > (seft *glob* 2000) 2000 > (let ((n 10)) (setf n 2) 2 La distinci´ on propia es entre variables lexicas y especiales. Para evitar errores accidentales con los nombre de las variables.11. Existe otro tipo de variables llamadas globales. la funci´ on vuelve a llamarse a si misma: > (preguntar-num) Por favor. que son visibles donde sea2 . Si el usuario ha escrito algo que no es un n´ umero. se puede usar boundp: > (boundp ’*glob*) T 2. usando defparameter: > (defparameter *glob* 1970) *GLOB* Esta variable es visible donde sea. salvo en contextos que definan una variable local con el mismo nombre. Se puede usar para asignar valores a cualquier tipo de variable. Se puede crear una variable global con un s´ ımbolo dado y un valor.

> (setf (car x) ’n) N > x (N B C) Se puede dar cualquier n´ umero de argumentos pares a setf. El primer argumento de setf puede ser tanto una expresi´ on. . Como sea. En el primer caso. se asume que se trata de una variable global. Se puede hacer m´ as que simplemente asignar valores a variables. > (setf x (list ’a ’b ’c)) (A B C) > (car x) A Esto es. en lugar de modificar cosas. es preferible usar explicitamente defparameter. se espera sean llamadas por el valor que producen y no por sus efectos colaterales.28 n) 2 Introducci´ on a Lisp 2 Cuando el primer argumento de setf es un s´ ımbolo que no es el nombre de una variable local. entre otras cosas. Es el paradigma de programaci´ on dominante en Lisp. como un nombre de variable. Una expresi´ on de la forma: > (setf a ’b c ’d e ’f) F es equivalente a: > (set a ’b) B > (set b ’c) C > (set e ’f) F 2. Programaci´ on funcional La programaci´ on funcional significa. escribir programas que trabajan regresando valores. es posible crear impl´ ıcitamente variables globales con s´ olo asignarles valores.12. Ej. el valor representado por el segundo argumento es insertado en el lugar al que hace referencia la expresi´ on. La mayor parte de las funciones predefinidas en el lenguaje.

evitar setf y otras expresiones con el mismo tipo de efecto colateral. se soprender´ an de lo poco que en realidad se necesita este tipo de efecto. se puede verificar cada funci´ on a medida que se va escribiendo. La lista original no es modificada: > lst (K A R A T E) Si se desea que la lista original sea afectada. escencialmente.2. mejos el objeto indicado: > (setf lst ’(k a r a t e)) (K A R A T E) > (remove ’a lst) (K R T E) ¿Por qu´ e no decir simplemente que remove remueve un objeto dado de una lista? Porque esto no es lo que la funci´ on hace.13 Iteraci´ on 29 La funci´ on remove. 2. se puede confiar en que es correcta. Si la funci´ on regresa los valores que esperamos. Iteraci´ on Cuando deseamos programar algo repetitivo. Ej. La confienza agregada al proceder de este modo. Una de las ventajas de la programaci´ on funcional es que permite la verificaci´ on interactiva. El caso t´ ıpico de iteraci´ on consiste en generar alg´ un tipo de tabla. se puede evaluar la siguiente expresi´ on: > (setf lst (remove ’a lst)) (K R T E) > lst (K R T E) La programaci´ on funcional significa. toma un objeto y una lista y regresa una nueva lista que contiene todos los elementos de la lista original.13. Si bien programar totalmente sin efetos colaterales es inconveniente. En c´ odigo puramente funcional. hace una gran diferencia: un nuevo estilo de programaci´ on. por ejemplo. a medida que practiquen Lisp. > (defun cuadrados (inicio fin) (do ((i inicio (+ i 1))) ((> i fin) ’final) (format t "˜A ˜A ˜ %" i (* i i)))) CUADRADOS > (cuadradros 2 5) 2 4 3 9 4 16 5 25 . algunas veces la iteraci´ on resulta m´ as natural que la recursividad. Esto puede parecer contra intuitivo y hasta no deseable.

dice – por cada obj en lst. Una funci´ on que calcula la longitud de una lista: > (defun longitud (lst) (let ((len 0)) (dolist (obj lst) (setf len (+ len 1))) len)) LONGITUD > (longitud ’(a b c)) 3 El primer argumento de dolist toma la forma (variable expresi´ on). La versi´ on recursiva obvia de esta funci´ on longitud es: . se evalua la prueba de fin de iteraci´ on y si esta falla. se evalua el cuerpo de do. constituyen el cuerpo del ciclo y ser´ an evaluados en orden en cada iteraci´ on. En cada iteraci´ on el valor de las variables definidas de esta forma. Para comparar. Ej. esta prueba es (> i fin). dolist para iterar sobre los elementos de una lista. las evalua en orden y regresa el valor de la u expresi´ on evaluada. El resto de la lista ser´ a eva´ ltima expresi´ luado en orden cuando la iteraci´ on termine. por lo que cuadrados. do puede crear variables y su primer argumento es una lista de especificaci´ on de variables.30 FINAL 2 Introducci´ on a Lisp La macro do es el operador fundamental de iteraci´ on en Lisp. El resto de los argumentos de do. cambia como lo especifica la actualizaci´ on. se presenta aqu´ ı una versi´ on recursiva de cuadrados-rec: > (defun cuadrados-rec (inicio fin) (if (> inicio fin) ’final (progn (format t "˜A ˜A ˜ %" inicio (* inicio inicio)) (cuadrados-rec (+ inicio 1) fin)))) CUADRADOS ´ nica novedad en esta funci´ La u on es progn que toma cualquier n´ umero de ex´ ltima presiones como argumentos. En la primer iteraci´ on i tomar´ a el valor de inicio y en las sucesivas iteraciones su valor se incrementar´ a en 1. do crea unicamente la variable local i. el resto de los argumentos son expresiones que constituyen el cuerpo de dolist. El segundo argumento de do debe ser una lista que incluya una o m´ as expresiones. Cada elemento de esta lista toma la forma (variable valor-inicial actualizaci´ on). Este cuerpo ser´ a evaluado con la variable instanciada con elementos sucesivos de la lista que regresa expresi´ on. Como let. donde: las variables son actualizadas. La u on evaluada ser´ a el valor de do. regresa siempre el valor ’final. La funci´ on del ejemplo. incrementar en uno len. Lisp provee operadores de iteraci´ on m´ as sencillos para casos especiales. En el ejemplo anterior. por ejemplo. En el ejemplo. La primera expresi´ on se usa como prueba para determinar cuando debe parar la iteraci´ on.

Una funci´ on que toma una funci´ on como argumento es apply. as´ ı que no necesitamos proteger su argumento. podemos usar #’. al terminar la recursividad. es decir. 2. > (apply #’+ ’(1 2 3)) 6 > (+ 1 2 3) 6 . cuya representaci´ on interna corresponde m´ as a un segmento de c´ odigo m´ aquina. que a la forma como la definimos. en Lisp podemos pasar funciones como argumentos. Esto no suecede con las funciones. nos regresar´ a el objeto asociado a ese nombre. la funci´ on debe seguir haciendo algo. Si le damos a function el nombre de una funci´ on. Ej. hemos trabajado con objetos que lucen igual cuando los escribimos y cuando Lisp los evalua.14.2. function es un operador especial.14 Funciones como objetos 31 > (defun longitud-rec (lst) (if (null lst) 0 (+ (longitud-rec (cdr lst)) 1))) LONGITUD Esta versi´ on ser´ a menos eficiente que la iterativa porque no es recursiva a la cola (tail-recursive). Funciones como objetos En Lisp las funciones son objetos regulares como los s´ ımbolos. Al igual que usamos ’ para abreviar quote. Ej. > #’+ #<Compiled-Function + 17BA4E> Como sucede con otros objetos. Como quote. para abreviar function. Hasta ahora. las cadenas y las listas. La definici´ on recursiva a la cola de longitud es: > (defun longitud-tr (lst) (labels ((longaux (lst acc) (if (null lst) acc (longaux (cdr lst) (+ 1 acc))))) (longaux lst 0))) LONGITUD-TR Lo nuevo aqu´ ı es labels que permite definir funciones locales como longaux. > (function +) #<Compiled-Function + 17BA4E> Esta extra˜ no valor corresponde a la forma en que una funci´ on ser´ ıa desplegada en una implementaci´ on Lisp.

Ej. Tambi´ en podemos usar este truco para computar mapeos sobre listas: CL-USER> (mapcar #’(lambda(x) (* 2 x)) ’(1 2 3 4)) (2 4 6 8) CL-USER> (defun dobles (lst) (mapcar #’(lambda(x)(* 2 x)) lst)) DOBLES CL-USER> (dobles ’(1 2 3 4)) (2 4 6 8) . > (funcall #’+ 1 2 3) 6 La macro defun crea una funci´ on y le da un nombre. Ej. Puede ser el primer elemento de una llamada de funci´ on: > ((lambda (x) (+ x 100)) 1) 101 o usarse con funcall: > (funcall #’(lambda (x) (+ x 100)) 1) 101 Entre otras cosas. > (apply #’+ 1 2 ’(3 4 5)) 15 La funci´ on funcall hace lo mismo. Para referirnos literalmente a un entero usamos una secuencia de d´ ıgitos. pero no necesita que sus argumentos esten empaquetados en forma de lista. si se respeta que el u ellos sea una lista. para referirnos literalmente a una funci´ on usamos una expresi´ on lambda cuyo primer elemento es el s´ ımbolo lambda. seguido de una lista de par´ ametros y el cuerpo de la funci´ on. > (lambda (x y) (x + y)) Una expresi´ on lambda puede considerarse como el nombre de una funci´ on. esta notaci´ on nos permite usar funciones sin necesidad de nombrarlas. Como los otros tipos de objeto en Lisp. pero las funciones no tienen porque tener nombre y no necesitamos defun para crearlas. Ej. podemos definir a las funciones literalmente.32 2 Introducci´ on a Lisp ´ ltimo de Se le puede dar cualquier n´ umero de argumentos. Ej.

se expresan como listas. En muchos lenguajes. entonces podr´ ıamos describir a Lisp como el lenguaje para describir Lisp. Imaginen que cada objeto en Lisp tiene asociada una etiqueta que especifica su tipo. integer. number. Lisp incluye una jerarqu´ ıa predefinida de subtipos y supertipos.2. que son objetos del lenguaje tambi´ en.16. pero eso es una historia totalmente diferente. En Lisp. en orden de generalidad incremental.16 Consideraciones 33 2. Un lenguaje con una sola sint´ axis para expresar programas y datos. Tipos Lisp utiliza un inusual enfoque flexible sobre tipos. es algo distinto de un lenguaje para escribir una clase part´ ıcular de aplicaciones. Las funciones. Ej. No debe preocuparles que la relaci´ on entre todas estas ideas no sea del todo clara. es posible definir el tipo de una variable para optimizar el c´ odigo antes de la compilaci´ on. programado casi por completo con funciones Lisp que en nada difieren a las que podemos definir. De cualquier forma. Un lenguaje que puede ser escrito en si mismo. No es necesario declarar el tipo de una variable porque cualquier variable puede recibir cualquier objeto de cualquier tipo. Consideraciones Aunque este documento presenta un bosquejo r´ apido de Lisp. Y Lisp mismo es un programa Lisp. Si C es el lenguaje para escribir UNIX3 . ¡el lenguaje puede mejorarse para acomodarse al programa! Esto es un buen inicio para entender la escencia de Lisp. los valores tienen un tipo. las variables tienen un tipo asociado y no es posible usar una variable sin especificar su tipo. La funci´ on typep toma como argumentos un objeto y un especificador de tipo y regreta t si el objeto es de ese tipo.15. Ofrece una nueva forma de programar: as´ ı como es posible escribit un programa en el lenguaje. Este enfoque se conoce como tipificaci´ on manifiesta. El tipo t es el supertipo de todo tipo. Ej. Un objeto siempre tiene m´ as de un tipo. que son a su vez objetos en Lisp. es posible apreciar ya el retrato de un lenguaje de programaci´ on inusual. Esta sint´ axis se basa en listas. real. Solo una cosa debe estar clara: Las ideas detr´ as Lisp son extremadamente elegantes. rational. Lisp introduce tal cantidad de conceptos nuevos que toma tiempo acostumbrarse a ellos y como usarlos. no las variables. 3 Richard Gabriel . atom y t. el n´ umero 27 es de tipo fixnum. > (typep 27 ’integer) T 2.