[plt-scheme] Some syntax issues
From: Lauri Alanko (la at iki.fi)
Date: Wed Aug 14 04:09:25 EDT 2002 |
|
Hello.
I'm trying to define a macro that expands to the definition of a macro
that expands to use a "private" variable that is visible nowhere else.
Here's a simple example:
(define-syntax (define-thingy stx)
(syntax-case stx ()
((_ macro-name)
(with-syntax ((var-name (syntax-local-introduce
(car (generate-temporaries #'(macro-name))))))
#'(begin
(define var-name 11)
(define-syntax (macro-name stx2)
(syntax-case stx2 ()
((_ a) #'(set! var-name a))
(i (identifier? #'i) #'var-name))))))))
In drscheme this seems to work fine, but in mzscheme this causes a
segfault. (I would have submitted a bug report, but the bug report
system is not very sneakernet-friendly. See Debian's bug system, it uses
plain email.)
Thankfully, the following modification seems to work too:
(... (with-syntax ((var-name (datum->syntax-object
#'macro-name
(gensym (syntax-object->datum #'macro-name)))))
...))
Still, this seems a bit awkward. Is there a reason why
generate-temporaries gives doesn't give the generated identifiers the
same syntactic context as its arguments? Now pure generate-temporaries
-generated identifiers are fairly useless, since their context doesn't
have #%top bound...
Also, I don't much like the fact that I have to use manually generated
unique identifiers. Hygienic macros are supposed to liberate us from the
endless gensyms of defmacro. Is there any cleaner way of defining a
variable that is to be used only from a macro?
Oh, and let me here voice my opinion that with the advent of
quasisyntax, the whole chez syntax-case system is becoming redundant.
Syntax-case patterns bind syntax objects to special pattern variables
which are distinct from ordinary variables. The only reason for this is
that then the (syntax ...) form can recognize those identifiers that are
to be replaced with the bound pattern variables from those that are to
be used verbatim. But this is bad style: variables and verbatim values
should not look exactly the same.
Imagine that quote would work so that (let ((b 5) '(a b c))) would
evaluate to (a 5 c). This is basically how #' currently works. And it is
evil. That is why we have quasiquote and, now, quasisyntax. The special
pattern variables of the syntax-case system bring just trouble: one has
to prepend #' to all syntactic variables and use with-syntax instead of
let, even though there is no real conceptual difference.
So here's what I propose: add syntax object support to the "regular"
pattern matcher. It has all the fancy stuff of syntax-case (such as
guards) and lots of other goodies. And it binds patterns to real
variables. _And_ with it the difference between a variable and a quoted
value is evident from the _pattern_ and there is no need to consult a
separate list of literal identifiers.
The only real feature that syntax-case has and match doesn't is
ellipsis. But I for one use ellipsis very rarely with syntax-case.
Syntax-rules is another matter entirely. Syntax-rules is _pretty_.
Syntax-case isn't.
Oh, one final question: what's the easiest way to reload a module from a
REPL after modifying the file where it's defined?
Enough ranting for now.
Lauri Alanko
la at iki.fi