[plt-scheme] let-syntax bug

From: Andre van Tonder (andre at het.brown.edu)
Date: Wed Apr 7 10:37:58 EDT 2004

Bradd Szonye wrote: 

> As you point out, Scheme could
> have separate scoping rules for transformers and variables. 

I think that is necessary, since variable scoping cannot even be
completely determined until expansion is complete.  

>    ;; Example 4:
>    ;; Overlapping scopes
>    (let-syntax ((FOO ...))   FOO
>      (blah)                   |
>      (blah)                   |
>      (define (BAR) ...)       |  BAR
>      (blah)                   |   |
>      (blah))                  |   |
>    (blah)                         |
>    (BAR)                          |
>                                   V

I agree that this is confusing, but for a different reason.  Let-syntax
only exists at expansion time, during which there are no side effects.  It
therefore should not make sense to have more than one expression in its
body, if the body of a let-syntax is to denote a piece of syntax
to be expanded hygienically and substituted in the final program.  Only
when expansion is complete is it possible to determine lexical
scoping of the resulting text.   
Instead, R5RS confuses the issue by implicitly inserting a *hidden*
piece of extra text: an enclosing (let () ...), which
does not appear in the original text to be expanded above and is in
conflict with the principle fo least surprise.  That, to me,
is confusing and unnecessary, since if that was my intention I would have
written (as required in Chez):

    (let-syntax ((FOO ...))   
      (let ()
        (blah)                   
        (blah)                   
        (define (BAR) ...)       
        (blah)                   
        (blah))                  

Instead, R5RS conflates an expand-time binding construct with a run-time
scoping construct.  My problem was that the above was not my intention.
Instead, I wanted

    (let-syntax ((FOO ...))   
      (begin
        (blah)                   
        (blah)                   
        (define (BAR) ...)       
        (blah)                   
        (blah))                  

and with R5RS there is no way to do that.  This makes R5RS strictly less
expressive, since there are macro-generating macros that I cannot write
with MzScheme syntax-rules, but which I have no problem writing in Chez.

>put DEFINE-SYNTAX inside LET-SYNTAX.) The language would need to define
>"transformer top level" and "variable/expression top level," and I think
>it would get confusing pretty quickly.

Syntax expansion and run-time have completely different semantics already.
Indeed, variable/expression top-level cannot even be determined until
expansion is complete.  

Regards
Andre    





Posted on the users mailing list.