5

Freenode 的#scheme 频道上提出了一个很好的问题。考虑 Scheme 中的以下代码:

(define alpha 1)

(define-syntax foo
  (syntax-rules (quote alpha)
    ((_ alpha msg) (define bar 2))
    ((_ other msg) (syntax-error msg)) ) )

(define (beta)
  (foo alpha "beta")
  (define alpha 3)
  'beta )

(define (gamma)
  (define alpha 4)
  (foo alpha "gamma")
  'gamma )

(define (delta alpha)
  (foo alpha "delta")
  'delta )

betagamma和中的哪些delta应该产生语法错误?哪一个呢?我已经用 Chibi Scheme 进行了检查,在哪里beta都可以,但gamma失败delta了。我想知道这是有意的行为还是只是 Chibi 中的错误。

根据标准,似乎应该在内部定义被重写之前扩展宏letrec*。因此betagamma两者都应该失败,因为foo将匹配内部定义alpha的,而不是全局的。

但是,标准中没有明确规定内部定义的实际工作方式,只是可以将它们视为 letrec 快捷方式。我在 Racket 的 R5RS 上得到了相同的行为,所以我似乎在标准中遗漏了一些需要这种行为的东西。

4

3 回答 3

1

好吧,我终于明白你的问题了。运行你的代码很有挑战性,因为你似乎有一个“语法错误”函数,只有当它以完全扩展的代码结束时才会发出语法错误信号。任何。

我认为你的问题的答案是这样的:

这些 Scheme 家伙(Dybvig、Felleisen、Hieb、Clinger、Rees、Wand、Flatt、Culpepper 等)非常聪明!

特别是,Scheme/Racket 以某种方式设法弄清楚绑定结构是如何工作的,即使它不知道什么将成为绑定。你是对的!太疯狂了!但是 Dybvig 等人概述的算法。做了一些非常聪明的事情来确保卫生跟踪标识符是“free-identifier-equal”还是“bound-identifier-equal”(Flatt 的术语),即使它还不知道哪个绑定了另一个。我个人建议阅读“一起工作的宏”(Flatt、Culpepper、Darais、Findler)以更好地理解这一点。

如果我误解了你的问题,或者我的语气不恰当,我深表歉意!

于 2014-09-24T15:49:14.070 回答
1

取决于实现方面可能有点太多,但这种行为是因为宏扩展的顺序。从理论上讲,所有定义都包含alpha,因此它不应与文字关键字中的定义匹配。但是,宏扩展需要在define表单扩展为之前进行letrec*,否则编译器无法正确检测到内部定义。所以在那一刻,编译器可能会也可能不会看到绑定。(宏扩展时序在R7RS上没有指定,实现时也可以选择自己的时序。)

对于这种beta情况,编译器没有捕获绑定,因此宏扩展器仍然可以看到它alpha与全局绑定相同。其他情况则相反。

于 2015-02-09T15:33:56.143 回答
0

首先,deltais out (should not match alpha) 因为它显然在词法上绑定alpha到另一个绑定,而不是你sytnax-rules出现的绑定。有趣的是betagamma

根据第 5.2.2 节。R4RS (p. 13) 和 R5RS (p. 16),第 5.3.2 节。R7RS(第 26 页)和第 11.3 节。在 R6RS (p. 32) 中,通过内部定义建立的绑定的“区域”是<body>定义出现的整体。并且您的宏调用foo显然与<body>那些内部定义相同。

R7RS 还走得更远,警告我们:

请注意,在扩展其他语法之前,这样的主体[即包含内部定义的主体]可能并不明显。

因此,事件的混乱顺序得到承认,但没有歧义;如果与宏调用 相同的任何内部定义存在绑定,则syntax-rules不应匹配分支。因此,并且也被淘汰了。alphaalpha<body>betagamma

附录 A

如果我们进一步使情况复杂化,并且您的宏本身有条件地绑定alpha,例如

(syntax-rules (alpha)
  ((_ alpha x) (define alpha x)))

那么乍一看似乎真的模棱两可,但我相信这是通过宏扩展器将alpha根据卫生情况重命名定义的标识符这一事实来解决的,这意味着我们不会将alpha我们匹配为文字的那个隐藏起来,所以匹配它是很好,上面将简单地为alpha在宏体之外无法访问的重命名创建绑定。

附录 B

第 5.3 节末尾有一个约束。R5RS (p. 17),第 5.4 节结束。R7RS (p. 26) 和 R6RS (p. 30) 第 10 节的中间部分,其中提到定义序列不应包含改变其中任何一个含义的定义。(实际上要复杂一点,所有三个标准都使用不同的措辞,但这应该是一个合理的总结。)

在您的示例中,我不清楚您syntax-rules扩展为语法错误的可能性是否算作其“含义”的歧义。如果有人认为这是一种歧义,那么您的betagamma是 R5RS 和 R7RS 的“错误”(未定义的行为),以及 R6RS 的“语法违规”。

如果您的示例在您的第二个分支中包含另一个绑定syntax-rules(理想情况下甚至是同一变量的定义),那么这个 nitpick 将不适用,所以您的问题成立。

于 2015-05-29T14:50:33.843 回答