2014-09-23 50 views
5

Freenode的#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) 

哪个betagammadelta应该产生语法错误的吗?而哪个?我已经用赤壁计划检查了这个,其中beta很好,而gammadelta失败。我想知道这是一个有意的行为还是仅仅是赤壁的一个bug。

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

但是,没有明确的标准规定内部定义是如何工作的,只是他们可以被作为letrec快捷想到的。我使用Racket的R5RS获得了相同的行为,所以看起来我错过了标准中要求这种行为的东西。

+0

在R6RS(基于psyntax的impl)中,调用过程时我得到相同的行为。 – leppie 2014-09-26 07:40:54

回答

1

好吧,我终于明白你的问题。运行你的代码是有挑战性的,因为你似乎有一个'语法错误'函数,只有在完全展开的代码中才会发出语法错误。随你。

我想回答你的问题是这样的:

这些计划家伙(Dybvig,Felleisen,Hieb,克林格,里斯,魔杖,弗拉特,卡尔佩珀等),是相当聪明!

特别是,不知何故Scheme/Racket能够找出绑定结构是如何工作的,即使它不知道绑定是否是绑定。你是对的!太疯狂了!但是Dybvig等人提出的算法。做一些非常聪明的事情,以确保卫生跟踪标识符是否“自由标识符相等”或“绑定标识符相等”(弗拉特的术语),即使它还不知道哪一个绑定另一个。我个人建议阅读“共同工作的宏”(Flatt,Culpepper,Darais,Findler)以更好地理解这一点。

道歉,如果我误解了你的问题,或者我的语气不合适!

1

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

对于beta情况下,编译器没赶上绑定,宏观扩张仍然可以看到alpha是相同的具有全球约束力。其他情况是相反的。

0

首先,delta超出(应该不匹配alpha),因为它清楚地词法结合alpha比相互结合下,你的sytnax-rules出现。有趣的是betagamma

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

R7RS也又进了一步,并警告我们:

需要注意的是这样一个机构[即一个包含内部定义]在扩展其他语法之前可能不明显。

所以事件的混乱顺序被承认,但没有歧义;如果与alpha的分支绑定的位置与调用宏时相同的<body>中的任何内部定义不匹配,则syntax-rules应该与alpha分支不匹配。 因此,betagamma也出来了。

附录A

如果我们使情况更加复杂,并且您的宏自身条件的约束alpha,像

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

的话,好像在首先想到真正的暧昧,但我相信这是通过这样一个事实解决了这个事实:宏扩展器将根据卫生重新命名定义的alpha标识符,这意味着我们不会将我们正在匹配的alpha映射为文字,因此匹配它很好,并且th上面的e将简单地创建一个在宏体外部无法访问的重命名的alpha的绑定。

附录B

有一个在5.3节的端部的约束。的R5RS(第17页),第5.4节结尾。 (第26页)和第10部分的中间部分。在R6RS(第30页)中,提到的定义序列不应包含改变其中任何一个的含义的定义。 (这实际上是一个有点复杂,使用这三种标准的不同写法,但应该是一个合理的摘要。)

在您的例子,它是我不清楚你syntax-rules的可能性是否扩大到语法错误计数作为其“含义”的模糊性。如果有人认为它是模糊的,那么您的betagamma是按照R5RS和R7RS的“错误”(未定义的行为),以及按照R6RS的“违反语法”。

如果您的示例在syntax-rules的第二个分支中包含另一个绑定(理想情况下甚至是同一个变量的定义),那么这个挑选将不适用,因此您的问题仍然存在。