【问题标题】:Julia local variable not defined in expression eval表达式 eval 中未定义 Julia 局部变量
【发布时间】:2020-05-23 03:22:11
【问题描述】:

给定以下函数,

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

如果我然后运行

floop(Symbol("b"))

我收到一条错误消息,提示 b 未定义。为什么这不起作用?我怎样才能做到这一点?

【问题讨论】:

标签: julia eval metaprogramming


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以执行类似以下宏的操作,在扩展时选择一个值,具体取决于静态已知的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 链。

    (实际上除了Symbol 之外,QuoteNode 中还可以有其他东西,但很难将它们拼接到宏调用中,而且它们也会引发 KeyError,所以我没有包含任何东西额外的处理。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      相关资源
      最近更新 更多