【问题标题】:Racket R6RS support: syntax-caseRacket R6RS 支持:语法案例
【发布时间】:2018-06-12 15:43:30
【问题描述】:

这个简单的 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 版本进行测试。

【问题讨论】:

    标签: scheme racket r6rs


    【解决方案1】:

    R6RS 的 Racket 实现在这种情况下并非不合规。事实上,如果有的话,它更严格地遵守标准:您编写的程序对导入阶段并不小心。问题在于define-syntax 在扩展时间期间评估其右侧,如11.2.2 Syntax definitions 部分所述:

    绑定到 的值,该值必须在宏扩展时计算到转换器。

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

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

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

    是以下之一:

    run
    expand
    (meta <level>)
    

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

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

    【讨论】:

    • 也适用于其他实现。太棒了,谢谢!
    猜你喜欢
    • 2015-04-20
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多