[plt-scheme] local special syntax confusion

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Wed Jan 2 23:16:47 EST 2008

Psy-Kosh wrote:
> A bit confused about locally redefining special syntax like #%app
> 
> What I mean is this:
> 
> (let-syntax ((#%app
>               (syntax-rules ()
>                 ((_ a b) (+ a b)))))
>   (3 5))
> 
> Produces 8 no problem.
> 
> on the other hand,
> 
> (define-syntax (blah stx)
>   (syntax-case stx ()
>     ((_ exp)
>      (with-syntax
>          ((#%app (datum->syntax-object #'exp '#%app)))
>        #'(let-syntax ((#%app
>                        (syntax-rules ()
>                          ((_ a b) (+ a b)))))
>            exp)))))
> 
> (blah (3 5))
> 
> produces the error "compile: identifier used out of context in: #%app"
> *blinks* huh?

Look at the application '(+ a b)' in the inner 'syntax-rules' template. 
The meaning of an application is determined by the nearest binding of 
'#%app' [1]. The application isn't in the scope of the nonhygienically 
introduced binding, because it's in the right-hand side of 'let-syntax'. 
The closest binding is the '#%app' bound using 'with-syntax'. But that 
binding disappears when the macro transformer returns; thus the "out of 
context" error.

You can usually catch "identifier used out of context" errors by looking 
at the local bindings within a macro and checking that they don't appear 
in any syntax expressions, like this:
   (define-syntax (m stx)
     (syntax-case stx ()
       [(m ___)
        (___ (let ([x ___])
               #'(___ x ___)))]))

In this case, the reference to '#%app' is implicit. And if it were 
explicit, it would be substituted away as a pattern variable. So it's an 
unusual case. My advice would be not to use the implicit syntax names 
(like '#%app', '#%datum', '#%top') as pattern variable names.

Ryan


[1] The closest binding with the right lexical context, rather.

> On the other other hand,
> 
> (define-syntax (blah stx)
>   (syntax-case stx ()
>     ((_ exp)
>      (with-syntax
>          ((app (datum->syntax-object #'exp '#%app)))
>        #'(let-syntax ((app
>                        (syntax-rules ()
>                          ((_ a b) (+ a b)))))
>            exp)))))
> 
> (blah (3 5))
> 
> produces 8 again.
> 
> I'm probably missing something really basic and obvious here, but no 
> clue what. So why does #2 fail while both #1 and #3 work?
> 
> Thanks
> 
> Psy-Kosh
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.