[plt-scheme] side effects in R6RS modules

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sun May 3 11:46:45 EDT 2009

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

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

Posted on the users mailing list.