[plt-scheme] side effects in R6RS modules
At Sun, 3 May 2009 10:13:13 +0200, Michele Simionato wrote:
>
> PLT Scheme (I am using version 4.1.5) is even more surprising:
>
> $ plt-r6rs x.ss
> /home/micheles/.plt-scheme/4.1.5/collects/experimental/defines.sls:5:0:
> compile: bad syntax; function application is not allowed, because no
> #%app syntax transformer is bound in the transformer environment in:
> (register (syntax a))
This is a bug in our R6RS implementation. It originates with a mismatch
between PLT Scheme's use of `#%app' to scope the application form and
R6RS's pair-unwrapping rules for templates produced by `syntax'.
In PLT Scheme, when you write
(+ 1 2)
then not only do the `+', `1', and `2', have a lexical context, but so
does the pair of parentheses. The meaning of function application is
determined by an `#%app' binding in the lexical context of the
parentheses. (You can also write `#%app' explicitly, if you prefer.)
If you write
#'(+ 1 2)
in R6RS, then there's an implicit `#%app' binding in all libraries (for
application as usual) so that it works out. But if you write
#'(+ 1 x)
and `x' is a pattern variable, then R6RS requires the result to be a
(mutable) pair, instead of a wrapped syntax object. Since the pair is
unwrapped, its lexical context has been lost.
Specifically, in your example, the application form
(register #'a)
in the template loses its context as it is unwrapped to match the R6RS
semantics of the enclosing #'. As the unwrapped syntax object becomes
the macro result, to fit the PLT Scheme macro system, the syntax object
is re-wrapped, but the context that is used (taken from the original
argument) doesn't have an `#%app' in the right phase. So, expansion
fails.
I'm not sure of the right solution to this problem, but I've committed
a better approximation. When `syntax' removes wrappers, it records the
wrapper in a hash table (weakly mapping the unwrapped value to its
wrapper). When an unwrapped syntax object becomes the result of a macro
expansion, the previously removed wrappers can be restored.
There are R6RS programs where this strategy won't work, including
programs that use `cons' directly instead of the `syntax' template
form. I'll have to think more about how to improve the implementation
further and how to document the remaining non-conformance with R6RS.
With the now-committed changes, your example prints a registration of
`a' followed by a registration of `b', and the resulting list is '(a
b).