The R5RS spec states that as part of the requirements for a macro defined using syntax-rules
:
If a macro transformer inserts a free reference to an identifier, the reference refers to the binding that was visible where the transformer was specified, regardless of any local bindings that may surround the use of the macro.
I am trying to understand how this works in practice. So for example, if I have the following code:
(define var 'original)
(define-syntax test-var
(syntax-rules (var)
((_ var)
var)
((_ pattern-var)
'no-match)))
I would expect the following, if executed immediately after, to evaluate to original
, which it does:
(test-var var)
And I would expect this one to be no-match
since the var
introduced into scope prior to test-var
does not match the binding of var
at macro definition:
(let ((var 1)) (test-var var))
However the following example has me puzzled:
(define var 'new-var)
(test-var var)
In Chicken Scheme, this evaluates to new-var
. I would have expected it to be no-match
for the same reasons as the previous (let)
example. I thought that perhaps this was an issue with using define
twice, but the result is still new-var
even if I use (set! var 'new-var)
Does anyone have any insight as to what is going on here? What should happen per R5RS?
This is the usual trick that Schemes have when dealing with redefinitions on the REPL -- treating them as a mutation for the existing binding. So the second
define
is not really creating a new binding, and instead it justset!
s the existing one.