Scheme中的宏和内部定义

时间:2014-09-23 23:28:11

标签: macros scheme r7rs

在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中的哪些会产生语法错误?哪些?我已经使用Chibi Scheme检查了这一点,其中beta正常,gammadelta失败。我想知道这是一个预期的行为还是仅仅是Chibi的一个错误。

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

但是,标准 内部定义实际上没有明确指定,只有它们可以被认为是letrec快捷方式。我对Racket的R5RS有同样的行为,所以我似乎缺少标准中需要这种行为的东西。

3 个答案:

答案 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出现的绑定。有趣的是betagamma

根据第5.2.2节。 R4RS(第13页)和R5RS(第16页),第5.3.2节。 R7RS(第26页)和第11.3节。 R6RS(第32页),&#34;地区&#34;通过内部定义建立的绑定是定义出现的整个<body> 。您对foo的宏调用显然与内部定义相同<body>

R7RS也进一步向我们发出警告:

  

请注意这样的身体[即在扩展其他语法之后,可能不会显示包含内部定义的内容。

因此,事件的混乱顺序被接纳,但没有歧义;如果syntax-rulesalpha的任何内部定义绑定alpha,则<body>beta分支不匹配。 因此,gammaalpha也不存在。

附录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;如果一个人认为这是一种暧昧关系,那么您的betagamma就会出现#34;错误&#34; (未定义的行为)根据R5RS和R7RS,以及&#34;语法违规&#34;根据R6RS。

如果你的例子在syntax-rules的第二个分支中包含另一个绑定(理想情况下是同一个变量的定义),那么这个挑剔将不适用,所以你的问题就可以了。