Macros 方案语法规则(let)和(define)之间变量绑定的差异
R5RS规范规定,作为使用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))) 如果在之后
语法规则定义的宏要求的一部分:
如果宏转换器插入对标识符的自由引用,则该引用将引用在指定转换器的位置可见的绑定,而不考虑宏使用周围的任何本地绑定
我试图理解这在实践中是如何起作用的。例如,如果我有以下代码:
(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!)
具有相同的效果(如果
被绑定)。”。所以我猜阴谋家们会想到这一点。但是在没有模块系统的情况下工作是相当过时的,依赖于顶层的代码应该限制在快速游戏和调试上。。。至少在国际海事组织。