这个简单的 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.
因此,在run
和expand
阶段都需要导入(rnrs base)
,并且需要导入 (rnrs 语法案例)
在扩展阶段。您可以使用以下程序来完成此操作:
#!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 - Racket R6RS支持: syntax-case,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50821083/