Macros 方案语法规则(let)和(define)之间变量绑定的差异

Macros 方案语法规则(let)和(define)之间变量绑定的差异,macros,scheme,hygiene,Macros,Scheme,Hygiene,R5RS规范规定,作为使用语法规则定义的宏要求的一部分: 如果宏转换器插入对标识符的自由引用,则该引用将引用在指定转换器的位置可见的绑定,而不考虑宏使用周围的任何本地绑定 我试图理解这在实践中是如何起作用的。例如,如果我有以下代码: (define var 'original) (define-syntax test-var (syntax-rules (var) ((_ var) var) ((_ pattern-var) 'no-match))) 如果在之后

R5RS规范规定,作为使用
语法规则定义的宏要求的一部分:

如果宏转换器插入对标识符的自由引用,则该引用将引用在指定转换器的位置可见的绑定,而不考虑宏使用周围的任何本地绑定

我试图理解这在实践中是如何起作用的。例如,如果我有以下代码:

(define var 'original)

(define-syntax test-var
 (syntax-rules (var)
   ((_ var)
    var)
   ((_ pattern-var)
    'no-match)))
如果在之后立即执行,我希望以下内容的计算结果为
original
,它确实如此:

(test-var var)
我认为这一点是不匹配的,因为在
测试var
之前引入范围的
var
与宏观定义下的
var
绑定不匹配:

(let ((var 1)) (test-var var))
然而,下面的例子让我感到困惑:

(define var 'new-var)
(test-var var)
在Chicken方案中,其计算结果为
newvar
。我本以为它是
不匹配的
,原因与前面的
(let)
示例相同。我认为这可能是两次使用
define
的问题,但结果仍然是
newvar
,即使我使用
(set!var'newvar)


有人知道这里发生了什么吗?每个R5R应该发生什么?

这是Scheme在处理REPL上的重新定义时通常采用的技巧——将它们视为现有绑定的突变。所以第二个
define
并不是真正创建一个新绑定,而是
set是现有的。

有趣的。。。虽然这种行为不仅发生在REPL上,而且也发生在通过解释器甚至编译版本的代码运行时。所以说这不是指定的行为是正确的,但大多数Schemer都希望它以这种方式工作?嗯,“REPL”指的是“隐式全局命名空间”的任何使用,与使用通常禁止重新定义的模块系统不同⁵RS说:“在程序的顶层,定义
(define)
基本上与赋值表达式
(set!)
具有相同的效果(如果
被绑定)。”。所以我猜阴谋家们会想到这一点。但是在没有模块系统的情况下工作是相当过时的,依赖于顶层的代码应该限制在快速游戏和调试上。。。至少在国际海事组织。