The Racket implementation of R6RS is not non-compliant in this case. Indeed, if anything, it is obeying the standard more closely: your program as-written is not careful about import phases. The problem is that define-syntax
evaluates its right-hand side during expand-time, as noted by section 11.2.2 Syntax definitions:
Binds <keyword> to the value of <expression>, which must evaluate, at macro-expansion time, to a transformer.
Unlike other Scheme standards, R6RS takes care to distinguish between phases, since it permits arbitrary programming at compile-time (while other Scheme standards do not). Therefore, section 7.1 Library form specifies how to import libraries at specific phases:
Each <import spec> specifies a set of bindings to be imported into the library, the levels at which they are to be available, and the local names by which they are to be known. An <import spec> must be one of the following:
<import set>
(for <import set> <import level> ...)
An <import level> is one of the following:
run
expand
(meta <level>)
where <level> represents an exact integer object.
Therefore, you need to import (rnrs base)
at both the run
and expand
phases, and you need to import (rnrs syntax-case)
at the expand phase. You can do this with the following program:
#!r6rs
(import (for (rnrs base) run expand)
(for (rnrs syntax-case) expand)
(rnrs io simple))
(define-syntax stest
(lambda (x)
(syntax-case x ()
((_ z) #'(z 0)))))
(stest display)
This program works in Racket. I have not tested if it also works on the other Scheme implementations you listed, but it ought to if they are standards-compliant.