Prev Up Next
Here is a definition of a rather more complicated
macro, fluid-let (sec 5.2).
fluid-let specifies temporary bindings for
a set of already existing lexical variables. Given a
fluid-let expression such as
(fluid-let ((x 9) (y (+ y 1)))
(+ x y))
we want the expansion to be
(let ((OLD-X x) (OLD-Y y))
(set! x 9)
(set! y (+ y 1))
(let ((RESULT (begin (+ x y))))
(set! x OLD-X)
(set! y OLD-Y)
RESULT))
where we want the identifiers OLD-X, OLD-Y,
and RESULT to be symbols that will not capture
variables in the expressions in the fluid-let form.
Here is how we go about fashioning a fluid-let
macro that implements what we want:
(define-macro fluid-let
(lambda (xexe . body)
(let ((xx (map car xexe))
(ee (map cadr xexe))
(old-xx (map (lambda (ig) (gensym)) xexe))
(result (gensym)))
`(let ,(map (lambda (old-x x) `(,old-x ,x))
old-xx xx)
,@(map (lambda (x e)
`(set! ,x ,e))
xx ee)
(let ((,result (begin ,@body)))
,@(map (lambda (x old-x)
`(set! ,x ,old-x))
xx old-xx)
,result)))))
The macro's arguments are:
xexe, the list of
variable/expression pairs introduced by the fluid-let; and
body, the list of
expressions in the body of the fluid-let. In our
example, these are ((x 9) (y (+ y 1))) and ((+ x
y))
respectively.
The macro body introduces a bunch of local variables:
xx is the list of the variables extracted from the
variable/expression pairs.
ee is the corresponding list of
expressions. old-xx is a list of fresh identifiers,
one for each variable in xx. These are used to
store the incoming values of the xx, so we
can revert the xx back to them once the
fluid-let body has been evaluated.
result is another
fresh identifier, used to store the value of the
fluid-let body. In our example, xx is (x y)
and ee is (9 (+ y 1)). Depending on how your
system implements gensym,
old-xx might be the
list (GEN-63 GEN-64), and result might be GEN-65.
The output list is created by the macro for our given
example looks like
(let ((GEN-63 x) (GEN-64 y))
(set! x 9)
(set! y (+ y 1))
(let ((GEN-65 (begin (+ x y))))
(set! x GEN-63)
(set! y GEN-64)
GEN-65))
which matches our requirement.
Prev Up Next