provided using mit-scheme
The only modification is from (cthen (make-syntactic-closure env '(it) (third exp)))
to (cthen (third exp))
In brief, what difference does make-syntactic-closure
make?
(define-syntax aif
(sc-macro-transformer
(lambda (exp env)
(let ((test (make-syntactic-closure env '(it) (second exp)))
(cthen (make-syntactic-closure env '(it) (third exp)))
(celse (if (pair? (cdddr exp))
(make-syntactic-closure env '(it) (fourth exp))
#f)))
`(let ((it ,test))
(if it ,cthen ,celse))))))
(let ((i 4))
(aif (memv i '(2 4 6 8))
(car it)))
(define-syntax aif
(sc-macro-transformer
(lambda (exp env)
(let ((test (make-syntactic-closure env '(it) (second exp)))
(cthen (third exp))
(celse (if (pair? (cdddr exp))
(make-syntactic-closure env '(it) (fourth exp))
#f)))
`(let ((it ,test))
(if it ,cthen ,celse))))))
(let ((i 4))
(aif (memv i '(2 4 6 8))
(car it)))
I tried the two version of macro, but got the same result.
A syntactic closure captures the syntactic environment and allows identifiers present in it to be used in the form as variables, instead of having a meaning provided by the environment of the macro transformer (It also lets you specify a list of free names like it
in this case that can be set or otherwise used in the macro body and have that binding used in the expanded form; basically it removes those names from the given environment)
An example:
(let ((i 4)
(x '(a b c)))
(aif (memv i '(2 4 6 8))
(car x)))
With the first version of your aif
macro, this evaluates to 'a
. With the second version, it generates an error Unbound variable: x
, because in the macro cthen
is a list, not a syntactic closure, and x
is unbound in the macro transformer so it can't be found when the expanded body is evaluated.