[plt-scheme] define-literal-set errors
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!