【发布时间】:2015-11-29 22:40:06
【问题描述】:
我试图从 macro hygiene 上的 Julia 元编程文档中的声明中理解。文档声称
Julia 的宏扩展器通过以下方式解决了这些问题。首先,宏结果中的变量分为局部变量或全局变量。如果变量被分配给(而不是声明为全局的)、声明为局部的或用作函数参数名称,则该变量被视为局部变量。否则,它被认为是全局的。然后局部变量被重命名为唯一的(使用生成新符号的 gensym() 函数),全局变量在宏定义环境中解析。因此,上述两个问题都得到了处理;宏的局部变量不会与任何用户变量冲突,并且 time 和 println 将引用标准库定义。
我写了一个小程序,看看在宏定义环境中是否确实解析了全局变量。我写了以下内容:
f(x) = x + 100
macro g() # According to Julia docs, ...
:(f(x) + 5) # ... f is global, x is local, right?
end # if so, f should refer to the f above?
(function main()
local x = 3
f(x) = x - 100 # f in the call environment subtracts 100
println(@g()) # So why does this do -92?
end)()
如果我要正确理解 Julia 文档,宏卫生的一部分是确保在宏的返回表达式中调用的任何函数都不会被调用者环境中的同名函数劫持。但这正是这里发生的情况,使用的函数 f 是本地定义的函数。
我原以为我必须使用esc 才能在调用点使用f。但事实并非如此,为什么呢?
另外,我注意到宏结果中的变量x被认为是本地的,所以应该为它生成一个新的gensymed变量名,以免与宏中的x发生冲突通话环境。但这也没有发生!
我如何阅读文档以了解此处不需要使用 esc 的原因?
编辑(澄清)
当我声称
f是全局的并且x是本地的时,根据文档,我这样做是因为我看到x被用作函数参数。我知道x没有被写入或声明为本地的,而且它确实看起来是全局的,但那些文档声称函数参数也应该是全局的!我知道卫生的常见部分,其中局部变量的 gensymming 可确保宏调用者上下文中的同名变量不会无意中粘贴。然而,文档声称对于函数,在宏定义的上下文中看到的那些被调用者使用它们自己的保护。这部分对我来说毫无意义,因为我的实验表明并非如此。
【问题讨论】:
-
哇,这仍然是一个悬而未决的问题?