[plt-scheme] define-literal-set errors

From: Neil Toronto (ntoronto at cs.byu.edu)
Date: Fri Sep 25 17:57:14 EDT 2009

Eli Barzilay wrote:
> On Sep 25, Neil Toronto wrote:
>> Version 4.2.1.8-svn14sep2009
>>
>> First error:
>>
>> (require (for-syntax syntax/parse))
>> (define-literal-set bars (bar))
>> ; expand: unbound identifier in module in: define-literal-set
>>
>> Fix:
>>
>> (require syntax/parse)
>> (define-literal-set bars (bar))
>>
>> But I have to (require (for-syntax syntax/parse)) because I'm using it 
>> within define-syntax. Is it typical to have to require a module 
>> for-syntax and not for-syntax?
> 
> IME, this happens very rarely because the kind of functionality that
> you need on each level is very different.  (I've had some cases where
> I needed things like `scheme/list' or `scheme/path' in both, but not
> much more than that.)
> 
> Specifically in this case, when you say "... because I'm using it
> within `define-syntax'" the first thing I'm thinking is that you're
> doing something wrong, and that not-for-syntax require is not going to
> help you[*].
> 
> 
>> Second error:
>>
>> (require syntax/parse
>>           (for-syntax syntax/parse))
>>
>> (define-literal-set bars (bar))
>>
>> (syntax-parse #'bar #:literal-sets (bars)
>>    [bar  #'0]
>>    [x    #'1])
>> ; = #'0
>>
>> (define-syntax (foo stx)
>>    (syntax-parse stx #:literal-sets (bars)
>>      [(_ bar)  #'0]
>>      [(_ x)    #'1]))
>> ; syntax-parse: expected identifier defined as a literal-set in: bars
>>
>> If I comment out the definition of (foo stx), the macro stepper says
>> that "bars" is unbound in the transformer phase.  I'm fairly sure
>> this is not my error. In the meantime, is there a way to copy the
>> definition of "bars" into the transformer phase?
> 
> I wouldn't be surprised at that -- `bars' is something that you need
> at the syntax phase, so you need to use it there instead of at the
> runtime.  As far as copying definitions from one phase to another --
> that's an even stronger sign that you're doing things wrong.
> 
> Just based on how it looks like (because I have nearly zero experience
> with `syntax/parse'), I think that this is what you want:
> 
>   #lang scheme
>   (require (for-syntax syntax/parse))
>   (begin-for-syntax
>     (define-literal-set bars (bar)))
>   (define-syntax (foo stx) ...)
> 
> But this doesn't work because of the limitation that Matthias referred
> to in his reply -- you can't use macros in a `begin-for-syntax'.  An
> easy way around that in this case (which seems to work) is:
> 
>   #lang scheme
>   (require (for-syntax syntax/parse))
>   (define-syntax foo
>     (let ()
>       (define-literal-set bars (bar))
>       (lambda (stx)
>         (syntax-parse stx #:literal-sets (bars)
>           [(_ bar)  #'0]
>           [(_ x)    #'1]))))
> 
> If you have several macros that need that `bars' definition, then you
> can use `define-syntaxes' to have them all in a single expression.
> 
> If you have enough code that makes this too verbose and/or
> inconvenient, then you can switch the whole code down to the runtime,
> and have a separate module that uses all of that at syntax-time -- and
> that's when you need to require `syntax/parse' normally and *not* for
> syntax (which is where [*] is needed).  The slightly tricky thing is
> to remember to require scheme `for-template', because everything has
> shifted down.
> 
>   #lang scheme
>   (require syntax/parse (for-template scheme))
>   (define-literal-set bars (bar))
>   (provide foo)
>   (define (foo stx)
>     (syntax-parse stx #:literal-sets (bars)
>       [(_ bar)  #'0]
>       [(_ x)    #'1]))
> 
> And now use it as:
> 
>   #lang scheme
>   (require (prefix-in * (for-syntax "x")))
>   (define-syntax foo *foo)
> 

That... was really long and helpful. Thanks!

Neil



Posted on the users mailing list.