为什么我在 Julia 宏中得到一个 UndefVarError

Why do I get an UndefVarError in Julia macro

我正在学习 Julia,特别是我正在尝试掌握宏,所以我发现,除其他外 Some useful macros for Julia - Github,在破译它们的过程中,我在 REPL 中得到了这种行为:

julia> macro once_then(expr::Expr)
         @assert expr.head == :while
         esc(quote
           $(expr.args[2]) # body of loop
           $expr # loop
         end)
       end
@once_then (macro with 1 method)

julia> i = 0
0

julia> @once_then while i < 10
       i += 1
       end
ERROR: UndefVarError: i not defined
Stacktrace:
 [1] macro expansion at ./REPL[34]:2 [inlined]
 [2] top-level scope at ./REPL[31]:5

julia> i
1

它显然在循环的第一次迭代中访问了 i,因为它增加了它,但随后 i 在第一次循环结束之间的某个地方变成了 Undefed循环和第二个的开始? 据我所知,esc 之后的括号应该包括循环结束之前的所有内容...

我只是将代码复制粘贴到终端中,我从 Julia language - Until loop 中的 @until 宏中得到了相同的行为,所以我认为问题不会来自代码本身...我遗漏了什么重要的东西吗?

(顺便说一句,我是 运行 1.0.4,所以这不应该是向后兼容性的问题...)

你的宏没问题。问题是所涉及变量的范围。 (有关更多信息,请查看:JuliaLang - Scope of Variables 简而言之,i = 0中的变量i是全局作用域,而循环是局部作用域。在 REPL 中,您可以添加关键字 global 让您的代码工作:

julia> @once_then while i < 10
       global i += 1
       end

另一个选项是在函数中完成所有这些,因此所有变量都具有局部作用域:

function fn()
i = 0
@once_then while i < 10
        i += 1
        end
    return i
end