[plt-scheme] Macro problem: struct name coincides with macro keyword
--- Lauri Alanko <la at iki.fi> wrote:
> On Wed, May 03, 2006 at 06:36:16PM +0200, Jens Axel Søgaard wrote:
> > (require (lib "42.ss" "srfi"))
> >
> > (list-ec (: j (index i)'(a b c))
> > (list i j))
> > (define-struct index (lexicon positions))
>
> > index: illegal use of syntax in: (index i)
>
> I mentioned a related problem a while ago:
>
>
http://list.cs.brown.edu/pipermail/plt-scheme/2006-March/012013.html
>
> > My first thought was to rename the imported "index" from 42.ss,
> > but index is not exported from 42.ss! It is used purely as
> > a keyword.
>
> What happens is that the the srfi-42 macros define the (usually
> unbound) _top-level_ identier "index" to be the special keyword,
> and you shadow that with your struct definition. You need to
> somehow import the top-level variable with a new name, but I'm
> not sure if that is possible. There is no "top-level" module...
>
> The real problem is with the srfi-42 implementation: it should
> define a dummy variable named "index" that acquires the keyword
> property (instead of the top-level variable). Then it could be
> imported and renamed normally. Alternatively (and I prefer this),
> since the keyword cannot appear in the same position as an
> expression, it should be compared just using its literal form
> instead of module-identifier=?.
I agree with both of your points, except in the first solution, the
srfi should define index as a macro that blows up when used out of
context:
(define-syntax index
(lambda (stx)
(raise-syntax-error #f "used out of context" stx)))
Danny Yoo, in another response, suggested using syntax parameters,
but since index is never "syntax-parameterized", that doesn't seem
necessary.
But really, the correct solution in this case seems to be using
literal/symbolic comparison on "index". It's unfortunate that Scheme
macros make doing the right thing more cumbersome in this case.
Another solution, when writing macros for just PLT Scheme, is to use
mzscheme's keyword datatype. Instead of index, use #:index. That's
another nice way to separate "potential expression" forms from
"special clause" forms, because (#:blah blah ...) can't be an
expression. Of course, that doesn't help at all for SRFIs.
Ryan