s14 Macros
Transcript of s14 Macros
-
8/19/2019 s14 Macros
1/23
Tema 5: Macros
Sesión 14: Macros
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
2/23
Hoy veremos...
• Conceptos generales
• Quasiquotation
• Macros en Scheme
• Ejemplos de macros
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
3/23
Referencias
• Capítulo 3.7 Programming Language Pragmatics: Macro Expansion
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
4/23
Definición de macro
• Una macro consiste en una plantilla o meta-expresión que define un patrón
de sustitución formado por unas variables libres y unas expresiones
textuales.
• Es una técnica de generación de código
• Se realiza en la fase de preprocesamiento (en lenguajes compilados como C
o C++)
• Previamente a la evaluación de la expresión (en lenguajes interpretados)
• Las macros son un meta-lenguaje, en el sentido de que permiten controlar y
definir expresiones del propio lenguaje
• No están sometidas a la sintaxis del lenguaje
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
5/23
Evolución histórica de las macros
• Orígen de las macros: ensamblador
• Se incorporan en lenguajes más próximos al ensamblador como C y en
lenguajes avanzados como LISP o Scheme como una posibilidad de
extender el lenguaje
• En la actualidad no se usan demasiado, aunque su característica de meta-
programación ha dejado una huella muy importante en los lenguajes de
programación:
• Anotaciones en Java
• Scaffolding en Ruby & Rails
• Herramientas de MDA de generación automática de código
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
6/23
Macros en C
• Ejemplos de Macros:
• Una llamada a la macro:
• Se sustituirá (expansión de la macro) por:
#define LINE_LEN 80
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define SWAP(a,b) {int t = (a); (a) = (b); (b) = t;}
x = MAX(p+q, r+s);
x = ((p+q) > (r+s) ? (p+q) : (r+s))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
7/23
Las macros permiten definir nuevos lenguajes
• Ejemplo en C:
• Lo probamos:
• Esta posibilidad es mucho más potente en las macros de Scheme
• Lenguajes de dominio: las universidades y departamentos de investigación
inventan lenguajes adaptados especificamente a dominios específicos como
robótica. Es muy fácil diseñar prototipos de estos lenguajes con las macros
de Scheme
#define then
#define begin {
#define end ;}
if (i > 0) then begin
a = 1;
b = 2
end
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
8/23
Problemas de la expansión en C
• El preprocesador de C extiende la macro de forma ciega sin tener ninguna
relación con el proceso de compilación posterior
• Esto puede producir errores. Por ejemplo, si llamamos a MAX(x++, y++) la
expansión de la macro produce el siguiente resultado:
• LISP y Scheme utilizan las llamadas macros higiénicas que encapsulan
implícitamente sus argumentos y evitan los errores de las macros de C
((a++) > (b++) ? (a++) : (b++))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
9/23
Quasiquotation
• La forma especial quasiquote junto con unquote permite evaluar de forma
arbitraria las expresiones que nos interesan en una lista:
• Se utiliza el símbolo backquote y la coma:
(define bar 2)
(quasiquote (foo (unquote bar) baz)) --> (foo 2 baz)
`(foo ,bar baz) --> (foo 2 baz)
(define a 2)
(define b 'hola)
'(1 a b)
(quasiquote (1 ,a ,b))
`(1 ,a ,b)
`(1 ,a ,b ,c)
`(1 ,+ ,-)
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
10/23
Macros en Scheme
• Se basan en las formas especiales define-syntax y syntax-rules
• Sintaxis de una macro:
• Ejemplo: mi-or
(define-syntax
(syntax-rules () (( )
...
( ))))
(define-syntax mi-or
(syntax-rules ()
((mi-or) #t)
((mi-or e) e)
((mi-or e1 e2 e3 ...)
(if e1 #t (mi-or e2 e3 ...)))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
11/23
Reglas de evaluación de una macro
• Para evaluar una llamada a una macro (op exp_1 ... exp_n) debemos
seguir las siguientes reglas:
• Buscar la definición de la macro. Buscar la forma especial define-
syntax en la que aparece op como clave.
• Emparejar. Buscar en la definición de la macro la regla sintáctica con la
que es posible emparejar la expresión (op exp_1 ... exp_n) que
estamos evaluando. Si hay más de una regla con la que se puede
emparejar la expresión, escogemos la primera de ellas.
• Transformar. Aplicar la regla para transformar la expresión.
• Evaluar. Evaluar la expresión resultante. En el caso en que la expresión
resultante contenga una llamada a una macro se evaluará siguiendo estasmismas reglas.
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
12/23
Expansión de una macro
• Expansión de la llamada a la macro:
(mi-or (equal? x 2) #f #t (equal? y 3))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
13/23
Sintaxis alternativas válidas
(define-syntax mi-or
(syntax-rules ()
((_) #t)
((_ e) e)
((_ e1 e2 e3 ...)
(if e1 #t (mi-or e2 e3 ...)))))
(define-syntax mi-or
(syntax-rules ()
((op) #t)
((op e) e) ((op e1 e2 e3 ...)
(if e1 #t (mi-or e2 e3 ...)))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
14/23
Depuración de macros
(define-syntax mi-or
(syntax-rules ()
((op) ‘#t)
((op e) ‘e) ((op e1 e2 e3 ...)
‘(if e1 #t (mi-or e2 e3 ...)))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
15/23
Macro make-procedure
(define-syntax make-procedure
(syntax-rules ()
((make-procedure (x ...) expr ...)
(lambda (x ...) expr ...))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
16/23
Macro mi-let
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
17/23
Macro mi-let
(define-syntax mi-let
(syntax-rules ()
((mi-let ((x v) ...) e ...)
((lambda (x ...) e ...) v ...))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
18/23
Macro mi-cond
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
19/23
Macro mi-cond
(define-syntax mi-cond
(syntax-rules (=> else)
((mi-cond (else => expr))
expr)
((mi-cond (test1 => expr1))
(if test1 expr1)) ((mi-cond (test1 => expr1) (test2 => expr2) ...)
(if test1 expr1 (mi-cond (test2 => expr2) ...)))))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
20/23
Macro multi-print (paradigma procedural)
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
21/23
Macro multi-print (paradigma procedural)
(define-syntax multi-print
(syntax-rules ()
((multi-print arg1 arg2 ...)
(begin (print arg1)
(newline)
(multi-print arg2 ...))) ((multi-print) #t)))
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
22/23
Macro when (paradigma procedural)
miércoles 23 de marzo de 2011
-
8/19/2019 s14 Macros
23/23
Macro when (paradigma procedural)
(define-syntax when
(syntax-rules ()
((when condition expr1 expr2 ...)
(if condition (begin expr1 expr2 ...) #f))))