【问题标题】:Macro call vs macro definition environment in JuliaJulia 中的宏调用与宏定义环境
【发布时间】: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 的原因?

编辑(澄清)

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

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

【问题讨论】:

标签: macros julia hygiene


【解决方案1】:

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

【讨论】:

  • 终于开始安装 0.6,是的,现在情况好多了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多