2

这个简单的 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: 变压器环境中的未绑定标识符;
此外,没有绑定 #%app 语法转换器

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

4

1 回答 1

4

在这种情况下,R 6 RS的 Racket 实现并非不兼容。事实上,如果有的话,它更严格地遵守标准:您编写的程序对导入阶段并不小心。问题是define-syntax在扩展时间评估其右侧,如第11.2.2 节语法定义所述:

将 <keyword> 绑定到 <expression> 的值,该值必须在宏扩展时对转换器求值。

与其他 Scheme 标准不同,R 6 RS 小心区分阶段,因为它允许在编译时进行任意编程(而其他 Scheme 标准则不允许)。因此,第7.1 节库形式指定了如何在特定阶段导入库:

每个 <import spec> 指定一组要导入到库中的绑定、它们可用的级别以及知道它们的本地名称。<import spec> 必须是以下之一:

<import set>
(for <import set> <import level> ...)

<import level> 是以下之一:

run
expand
(meta <level>)

其中 <level> 表示一个精确的整数对象。

因此,(rnrs base)runexpand阶段都需要导入(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 实现,但如果它们符合标准,它应该可以。

于 2018-06-12T16:15:21.670 回答