Você está na página 1de 23

Introduccion

Backquote

Definiendo macros

Probando macros

II
Metodologas de Programacion
Macros en Lisp

Dr. Alejandro Guerra-Hernandez


Departamento de Inteligencia Artificial
Facultad de Fsica e Inteligencia Artificial
aguerra@uv.mx
http://www.uv.mx/aguerra

Maestra en Inteligencia Artificial 2012

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Programas que escriben programas

de una macro es esencialmente el de una


La definicion
que genera codigo

funcion
Lisp un programa que genera
programas.
produce un resultado,
Diferencia importante: Una funcion
que al ser
pero una macro produce una expresion
evaluada produce un resultado.


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplo: nil!

Supongan que queremos escribir la macro nil! que


asigna a su argumento el valor nil. Queremos que
(nil! x) tenga el mismo efecto que (setq x nil)
CL-USER> (defmacro nil! (var)
(list setq var nil))
NIL!
CL-USER> (nil! x)
NIL
CL-USER> x
NIL

1
2
3
4
5
6
7

Como
evalua
Lisp la llamada en la lnea 4?

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

de una macro
Evaluacion

Lisp identifica a nil! como una macro y:


I

especificada por la definicion


de la
Construye la expresion
lo que
marco en la fase conocida como macro-expansion,
(setq x nil); y entonces
genera la expresion
obtenida en lugar de la llamada original
Evalua la expresion
a la macro, esto es, se evalua
(setq x nil), como si el
programador la hubiese tecleado.


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

solo
en algunas partes
Deteniendo la evaluacion

1
2
3
4
5
6
7
8

especial de nuestro conocido


El backquote es una version
quote, que puede ser usado para definir moldes de
expresiones Lisp.
CL-USER 3
(A B C)
CL-USER 4
(A B C)
CL-USER 5
3
CL-USER 6
(A (2 C))

> (list a b c)
> (a b c)
> (setf a 1 b 2 c 3)
> (a (,b c))


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Ventajas de backquote

1
2
3
4

faciles

Hace que las expresiones sean mas


de leer, debido
con apostrofo

a que la expresion
invertido es similar a su
Vean las definiciones de nil!
macro-expansion.
(defmacro nil!
(list setq
(defmacro nil!
(setq ,var

(var)
var nil))
(var)
nil))


Introduccion

Backquote

Definiendo macros

Probando macros

complejo: nif
Un ejemplo mas

I
1
2
3
4

un if numerico:
CL-USER 8 > (mapcar #(lambda(x)
(nif x p c n))
(0 2.5 -8))
(C P N)

Ejemplos


Introduccion

Backquote

Definiendo macros

Nif con apostrofo

1
2
3
4
5

(defmacro nif (expr pos zero neg)


(case (truncate (signum ,expr))
(1 ,pos)
(0 ,zero)
(-1 ,neg)))

Probando macros

Ejemplos


Introduccion

Backquote

Definiendo macros

Nif sin apostrofo

1
2
3
4
5
6

(defmacro nif (expr pos zero neg)


(list case
(list truncate (list signum expr))
(list 1 pos)
(list 0 zero)
(list -1 neg)))

Probando macros

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Coma-arroba

1
2
3
4
5
6

que en lugar de
Funciona como la coma normal, solo
que antecede, inserta su
insertar el valor de la expresion

externos:
valor removiendo los parentesis
mas
CL-USER 10 > (setq b (1 2 3))
(1 2 3)
CL-USER 11 > (a ,b c)
(A (1 2 3) C)
CL-USER 12 > (a ,@b c)
(A 1 2 3 C)

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplo de uso: mi-when

1
2
3

(defmacro mi-when (test &body body)


(if ,test
(progn ,@body)))

el parametro
&body toma un numero
arbitrario de argumentos

progn.
y el operador coma-arroba los inserta en un solo

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Definiendo macros simples

1
2

Se comienza con la llamada a la macro que queremos

definir. Escribirla en un papel y abajo escriban la expresion


que quieren producir con la macro:
llamada: (mem-eq obj lst)
expansi
on: (member obj lst :test #eq)


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Parametros
de la macro

La llamada nos sirve para definir los parametros


de la
macro. En este caso, como necesitamos dos argumentos,

el inicio de la macro sera:


(defmacro mem-eq (obj lst)


Introduccion

Backquote

Definiendo macros

Probando macros

Cuerpo de la macro
I

Para cada argumento en la llamada a la macro, tracen un

lnea haca donde son insertadas en la expansion.

Comiencen el cuerpo de la macro con un apostrofo


invertido.
expresion
por expresion:

Ahora lean la expansion


en la llamada,
1. Si no hay una lnea conectado la expresion
tal cual en el cuerpo de la
entonces escribir la expresion
macro.
escriban la expresion
precedida por
2. Si hay una conexion,
una coma.

1
2

(defmacro mem-eq (obj lst)


(member ,obj ,lst :test #eq))

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Macros de aridad indeterminada


I

(defmacro while (test &body body)


(do ()
((not ,test))
,@body))

1
2
3
4

I
1
2
3
4
5
6

Hay que recurrir a coma-arroba:

y obtenemos una nueva estructura de control


CL-USER> (let ((i 0))
(while (< i 10)
(princ i)
(setf i (1+ i))))
0123456789
NIL

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Macro expansiones

complejas, es necesario poder observar


Para macros mas
ha sido correcta.
si la expansion
Para ello lisp provee dos funciones predefinidas:
I

macroexpand muestra como la macro se expandira antes


de ser evaluada. Si la macro hace uso de otras macros,
de la expansion
es de poca utilidad.
esta revision
macroexpand-1 muestra la expansion
de un
La funcion
paso.
solo


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos de macro expansion

1
2
3
4
5
6
7
8
9
10

CL-USER 2 > (pprint(macroexpand


(while (puedas) (rie))))
(BLOCK NIL
(LET ()
(DECLARE (IGNORABLE))
(DECLARE)
(TAGBODY
#:G747 (WHEN (NOT (PUEDAS)) (RETURN-FROM NIL NIL))
(RIE)
(GO #:G747))))

11
12
13
14

CL-USER 3 > (pprint (macroexpand-1


(while (puedas) (rie))))
(DO () ((NOT (PUEDAS))) (RIE))

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Una meta macro

1
2

Si vamos a hacer esto muchas veces, nos convine definir


una macro:
(defmacro mac (expr)
(pprint (macroexpand-1 ,expr)))

de forma que podemos evaluar ahora:


1
2
3

CL-USER> (mac (while (puedas) rie))


(DO () ((NOT (PUEDAS))) RIE)
; Not value

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Ejemplos

Evaluando la expansion

1
2
3
4

obtenida puede evaluarse en el TOP-LEVEL


La expansion
para experimentar con la macro:
CL-USER> (setq aux (macroexpand-1 (mem-eq a (a b c))))
(MEMBER A (A B C) :TEST #EQ)
CL-USER> (eval aux)
(A B C)


Introduccion

Backquote

Definiendo macros

Probando macros

for, in y random-choice
1
2
3
4
5
6

(defmacro for (var start stop &body body)


(let ((gstop (gensym)))
(do ((,var ,start (1+ ,var))
(,gstop ,stop))
((> ,var ,gstop))
,@body)))

7
8
9
10
11
12

(defmacro in (obj &rest choices)


(let ((insym (gensym)))
(let ((,insym ,obj))
(or ,@(mapcar #(lambda(c) (eql ,insym ,c))
choices)))))

13
14
15
16
17
18
19

(defmacro random-choice (&rest exprs)


(case (random ,(length exprs))
,@(let ((key -1))
(mapcar #(lambda(expr)
(,(incf key) ,expr))
exprs))))

Ejemplos


Introduccion

Backquote

Definiendo macros

Corridas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

CL-USER 3 > (for x 1 8 (princ x))


12345678
NIL
CL-USER 4 > (in 3 1 2 3)
T
CL-USER 5 > (random-choice 1 2 3)
1
CL-USER 6 > (random-choice 1 2 3)
3
CL-USER 7 > (random-choice 1 2 3)
3
CL-USER 8 > (random-choice 1 2 3)
1
CL-USER 9 > (random-choice 1 2 3)
1
CL-USER 10 > (random-choice 1 2 3)
2

Probando macros

Ejemplos


Introduccion

Backquote

Definiendo macros

macro expansiones

1
2
3
4
5
6
7
8
9
10
11
12
13

CL-USER> (mac (for x 1 9 (princ x)))


(DO ((X 1 (1+ X))
(#:G1009 9))
((> X #:G1009)) (PRINC X))
; No value
CL-USER> (mac (in 3 1 2 3))
(LET ((#:G1010 3)) (OR (EQL #:G1010 1)
(EQL #:G1010 2)
(EQL #:G1010 3)))
; No value
CL-USER> (mac (random-choice 1 2 3))
(CASE (RANDOM 3) (0 1) (1 2) (2 3))
; No value

Probando macros

Ejemplos


Introduccion

Backquote

Definiendo macros

Probando macros

Bibliografa

P. Graham.
On Lisp: Advanced Techniques for Common Lisp.
Prentice Hall International, 1993.

Ejemplos

Você também pode gostar