Racket R6RS 支持:语法大小写

Racket R6RS support: syntax-case

这个简单的 R6RS 程序:

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

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

(stest display)

适用于 Chez、Guile 和 Ypsilon,但不适用于 Racket。它给了我这个:

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

我的问题是,R6RS 是否坏了,还是我必须做其他事情?我正在测试 6.12 版。

R6RS 的 Racket 实现在这种情况下并非不兼容。实际上,如果有的话,它更严格地遵守标准:您编写的程序不注意导入阶段。问题是 define-syntax 在扩展期间评估其右侧,如 11.2.2 Syntax definitions:

部分所述

Binds <keyword> to the value of <expression>, which must evaluate, at macro-expansion time, to a transformer.

与其他 Scheme 标准不同,R6RS 会注意区分阶段,因为它允许在编译时进行任意编程(而其他 Scheme 标准则不允许)。因此,第7.1 Library form节指定了如何在特定阶段导入库:

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.

因此,在runexpand阶段都需要导入(rnrs base),在expand阶段需要导入(rnrs syntax-case)。您可以使用以下程序执行此操作:

#!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)

此程序适用于 Racket。我没有测试它是否也适用于您列出的其他 Scheme 实现,但如果它们符合标准,它应该可以。