我试图通过macro hygiene上Julia的Metaprogramming文档中的陈述来理解。文件声称
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变量名,以免与{{1}冲突在宏调用环境中。但这也没发生!
我如何阅读文档以了解x
不需要在这里使用的原因?
当我声称esc
是全局的且f
是本地的时,根据文档,我这样做是因为我看到x
被用作函数参数。我理解x
没有写入或声明为本地,它肯定看起来全局,但那些文档声称函数参数也应该是全局的!
我知道卫生的通常部分,本地人的gensymming确保宏调用者的上下文中的同名变量不会无意中贴满。但是,文档声称,对于 functions ,宏定义的上下文中看到的那些使用它们自己来保护调用者。这是对我没有意义的部分,因为我的实验表明不是。
答案 0 :(得分:2)
这是一个错误。这是Julia 0.5及更早版本的旧版本,并已在Julia 0.6中修复。有关详细信息,请参阅https://github.com/JuliaLang/julia/issues/4873。