Here is an anaphoric if defined in Guile’s defmacro:
(define-macro
(aif-version-2 test then else)
`(let ((it ,test))
(if it ,then ,else)))
The problem with this is that let
and if
are also injected, not
just it. (The syntax-case
version on that page doesn’t have that
problem.)
So if you’re running aif-version-2
in an environment where let
or
if
is shadowed, you’re in trouble.
The entire selling point of the Scheme project was lexical scoping, after all (something Common Lisp also adopted just before the deadline kinda putting a wrench in the whole “common” idea as the big Lisps at the time struggled to implement lexical scoping).
In Common Lisp this shadow sensitivity doesn’t matter too much since they’re in a different name space anyway, although it’s not a surefire thing, so the traditional Common Lisp solution is to rename everything with gensyms.
In Chicken, they created a transformer that automatically does that, an “implicit renaming” macro transformer that implicitly renames everything you don’t “inject”. It’s a li’l bit wordy and verbose to use so I have define-ir-syntax* to make it simple to write macros:
(define-ir-syntax*
(aif-version-3 test then else)
`(let ((,(inject it) ,test))
(if it ,then ,else)))
It only injects it
, everything else (in this case if
and let
) are renamed.