在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 )
beta
,gamma
和delta
中的哪些会产生语法错误?哪些做?我已经使用Chibi Scheme检查了这一点,其中beta
正常,gamma
和delta
失败。我想知道这是一个预期的行为还是仅仅是Chibi的一个错误。
根据标准,似乎扩展宏应该在内部定义被重写为letrec*
之前发生。因此,beta
和gamma
都会失败,因为foo
将与内部定义的alpha
匹配,而不是全局定义的{{1}}。
但是,标准 内部定义实际上没有明确指定,只有它们可以被认为是letrec快捷方式。我对Racket的R5RS有同样的行为,所以我似乎缺少标准中需要这种行为的东西。
答案 0 :(得分:1)
好的,我终于了解你的问题。运行代码非常具有挑战性,因为您似乎有一个“语法错误”错误。只有当它在完全扩展的代码中结束时才发出语法错误信号的函数。不管。
我认为你的问题的答案是:
这些计划人员(Dybvig,Felleisen,Hieb,Clinger,Rees,Wand,Flatt,Culpepper等)非常聪明!
特别是,Scheme / Racket设法弄清楚绑定结构如何工作,即使它不知道什么是绑定。你是对的!真是太疯狂了!但是Dybvig等人提出的算法。做一些非常聪明的事情,以确保卫生跟踪标识符是否是" free-identifier-equal"或" bound-identifier-equal" (弗拉特的术语)即使它还不知道哪一个绑定另一个。我个人建议阅读"一起工作的宏#34; (Flatt,Culpepper,Darais,Findler)为了更好地理解这一点。
如果我误解了你的问题,或者我的语气不合适,我会道歉!
答案 1 :(得分:1)
根据实现方面可能有点过多,但这种行为是因为宏扩展的顺序。从理论上讲,所有定义都包含alpha
,因此它不应与文字关键字中的定义匹配。但是,在define
表单扩展到letrec*
之前,需要进行宏扩展,否则编译器无法正确检测内部定义。所以在那一刻,编译器可能会也可能不会看到绑定。 (宏扩展时序在R7RS上未指定 ,因此实现也可以选择自己的时序。)
对于beta
情况,编译器没有捕获绑定,因此宏扩展器仍然可以看到alpha
与全局绑定相同。其他情况则是相反的。
答案 2 :(得分:0)
首先,delta
已出局(不应与alpha
匹配),因为它明显将alpha
词汇绑定到另一个绑定,而不是sytnax-rules
出现的绑定。有趣的是beta
和gamma
。
根据第5.2.2节。 R4RS(第13页)和R5RS(第16页),第5.3.2节。 R7RS(第26页)和第11.3节。 R6RS(第32页),&#34;地区&#34;通过内部定义建立的绑定是定义出现的整个<body>
。您对foo
的宏调用显然与内部定义相同<body>
。
R7RS也进一步向我们发出警告:
请注意这样的身体[即在扩展其他语法之后,可能不会显示包含内部定义的内容。
因此,事件的混乱顺序被接纳,但没有歧义;如果syntax-rules
与alpha
的任何内部定义绑定alpha
,则<body>
与beta
分支不匹配。 因此,gamma
和alpha
也不存在。
附录A
如果我们进一步使情况复杂化,并且您的宏本身有条件地绑定(syntax-rules (alpha)
((_ alpha x) (define alpha x)))
,例如
alpha
然后它起初看起来真的很模糊,但我相信这是通过宏扩展器将按照卫生重命名定义的alpha
标识符的事实来解决的,这意味着我们不会遮蔽{{1}我们匹配它作为文字,所以匹配它很好,上面只会为重命名的alpha
创建一个在宏体外无法访问的绑定。
附录B
5.3节末尾有一个限制。 R5RS(第17页),5.4节末尾。 R7RS(第26页)和第6节中间的R6RS(第30页)中提到一系列定义不应包含改变其中任何含义的定义 。 (它实际上有点复杂,所有三个标准都使用不同的措辞,但这应该是一个合理的总结。)
在您的示例中,我不清楚您syntax-rules
扩展到语法错误的可能性是否构成其&#34;含义的歧义。&#34;如果一个人认为这是一种暧昧关系,那么您的beta
和gamma
就会出现#34;错误&#34; (未定义的行为)根据R5RS和R7RS,以及&#34;语法违规&#34;根据R6RS。
如果你的例子在syntax-rules
的第二个分支中包含另一个绑定(理想情况下是同一个变量的定义),那么这个挑剔将不适用,所以你的问题就可以了。