[plt-scheme] Possible hygiene bug?

From: Jim Blandy (jimb at redhat.com)
Date: Wed Oct 22 19:07:32 EDT 2003

"Bradd W. Szonye" <bradd+plt at szonye.com> writes:

>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> On Wed, Oct 22, 2003 at 04:09:43PM -0400, Andre van Tonder wrote:
> > I am having a problem with the following macro .... It seems that the
> > variable y is not introduced hygienically ....
> >
> > (define-syntax define-test 
> >   (syntax-rules ()
> >     ((define-test x name) 
> >      (define-syntax name
> >        (syntax-rules ()
> >          ((name) (lambda (x y) (x y))))))))
> > 
> > (define-test y tester)
> If I understand correctly, you expect this to expand to:
>     (define-syntax tester
>       (syntax-rules ()
>         ((tester) (lambda (y y') (y y')))))
> > ((tester) (lambda (x) x) 1)
> And this should expand to:
>     ([lambda (y y') (y y')] [lambda (x) x] 1)
>     ([lambda (x) x] 1)
>     1
> This is based on R5R6 4.3.2 Pattern Language:
>     Identifiers that appear in the template but are not pattern
>     variables or the identifier `...' are inserted into the output as
>     literal identifiers. If a literal identifier is inserted as a free
>     identifier then it refers to the binding of that identifier within
>     whose scope the instance of `syntax-rules' appears. If a literal
>     identifier is inserted as a bound identifier then it is in effect
>     renamed to prevent inadvertent captures of free identifiers.
> and R5R6 4.1.4 Procedures (lambda):
>     When the procedure is later called with some actual arguments, the
>     environment in which the lambda expression was evaluated will be
>     extended by binding the variables in the formal argument list to
>     fresh locations ....
> But looking again at your macro, x and y do not appear to be bound
> identifiers in the context of define-test, so y is not renamed. In other
> words, the lambda is not "binding" until you expand tester. I'm not sure
> whether this interpretation is correct, but it looks like the nested
> define-syntax "hides" the binding from define-test.

Actually, I'm pretty sure Andre's expectations are correct.  y only
appears bound in the template, not free, so it should be renamed.  If
there were a global binding of y in scope at define-test's definition,
and y appeared free in the template, then the expander would need to
make sure that those appearances always referred to that global
definition.  But as the example stands, the expander is only
responsible for making sure that the y in the lambda's body refers to
the lambda's second argument.

Posted on the users mailing list.