2
votes

This simple R6RS program:

#!r6rs
(import (rnrs base)
        (rnrs syntax-case)
        (rnrs io simple))

(define-syntax stest
  (lambda (x)
    (syntax-case x ()
      ((_ z) #'(z 0)))))

(stest display)

works with Chez, Guile and Ypsilon but not Racket. It gives me this:

test.scm:7:3: lambda: unbound identifier in the transformer environment;
also, no #%app syntax transformer is bound

My question is, is it broken for R6RS or do I have to do something else? I'm testing with version 6.12.

1

1 Answers

4
votes

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.