[plt-scheme] define-literal-set errors

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Sep 25 16:45:16 EDT 2009

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)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the users mailing list.