表达式 eval 中未定义 Julia 局部变量

Julia local variable not defined in expression eval

给定以下函数,

function floop(exp)
    a = 5
    b = 10
    ex = Expr(:call, :+, 1, exp);
    return eval(ex);
end

如果我那么运行

floop(Symbol("b"))

我收到一条错误消息,指出 b 未定义。为什么这不起作用?我怎样才能使这项工作?

让 Julia 变得快速的关键因素之一是 eval 始终在全局范围内运行。这意味着它永远不能引用局部变量。

您可以执行类似以下宏的操作,在扩展时选择一个值,具体取决于静态已知 Symbol:

julia> macro floop(selector::QuoteNode)
           choices = Dict(:a => 5, :b => 10)
           ex = :(1 + $(choices[selector.value]))
           return ex
       end
@floop (macro with 1 method)

julia> @macroexpand @floop(:a)
:(1 + 5)

julia> @macroexpand @floop(:b)
:(1 + 10)

julia> @floop(:c)
ERROR: LoadError: KeyError: key :c not found
Stacktrace:
 [1] getindex(::Dict{Symbol,Int64}, ::Symbol) at ./dict.jl:477
 [2] @floop(::LineNumberNode, ::Module, ::QuoteNode) at ./REPL[27]:3
in expression starting at REPL[33]:1

julia> s = :a; @floop(s)
ERROR: LoadError: MethodError: no method matching @floop(::LineNumberNode, ::Module, ::Symbol)
Closest candidates are:
  @floop(::LineNumberNode, ::Module, ::QuoteNode) at REPL[1]:2
in expression starting at REPL[2]:1

如何实际存储实际值取决于您。 const 全局字典是一个选项,或者只是一个简单的 if 链。

(在QuoteNode中其实可以有除Symbol之外的其他东西,但是很难将它们拼接到宏调用中,它们也只会引发一个KeyError ,所以我没有包括任何额外的处理。)