Julia 中的宏调用与宏定义环境

Macro call vs macro definition environment in Julia

我试图理解 macro hygiene 上 Julia 的元编程文档中的声明。该文档声称

Julia’s macro expander solves these problems in the following way. First, variables within a macro result are classified as either local or global. A variable is considered local if it is assigned to (and not declared global), declared local, or used as a function argument name. Otherwise, it is considered global. Local variables are then renamed to be unique (using the gensym() function, which generates new symbols), and global variables are resolved within the macro definition environment. Therefore both of the above concerns are handled; the macro’s locals will not conflict with any user variables, and time and println will refer to the standard library definitions.

我写了一个小程序,看看是否确实在宏定义环境中解析了全局变量。我写了以下内容:

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 变量名称,以免与 [= 冲突14=] 在宏调用环境中。但这也没有发生!

我如何阅读文档以弄清此处不需要使用 esc 的原因?

编辑(澄清)

  1. 当我声称 f 是全局的而 x 是本地的时,根据文档,我这样做是因为我看到 x 被用作函数参数。我知道 x 没有被写入也没有被声明为本地的,它肯定 看起来 是全局的,但是那些文档声称函数参数也应该是全局的!

  2. 我知道卫生的通常部分,其中局部变量的 gensymming 确保宏调用者上下文中的同名变量不会无意中贴上。然而,文档声称对于 函数 ,在宏 定义的 上下文中看到的那些使用它们自己的调用者受到保护。这是对我来说没有意义的部分,因为我的实验表明并非如此。

这是一个错误。这是 Julia 0.5 及更早版本的旧问题,已在 Julia 0.6 中修复。有关详细信息,请参阅 https://github.com/JuliaLang/julia/issues/4873