【问题标题】:How can I eval a local variable in Julia如何评估 Julia 中的局部变量
【发布时间】:2014-01-21 20:04:01
【问题描述】:
i = 50
function test()
  i = 10
  eval(:i)
end
test()  # => 50

为什么这会评估为全局 i 而不是本地的?有没有办法让它评估到本地?

【问题讨论】:

    标签: julia


    【解决方案1】:

    你不能。 Julia 的 eval 始终评估当前模块范围的代码,而不是您的本地范围。在本地范围内调用 eval 是一种反模式和性能杀手。但是,您可以构造一个新函数,其中包含一些引用本地范围的用户代码,然后调用该函数。例如:

    # user-supplied expression
    expr = :(i^2 + 1)
    
    # splice into function body
    test = @eval function ()
        i = 10
        $expr
    end
    

    现在您可以拨打test:

    julia> test()
    101
    

    为什么这比在问题中的test 内部调用eval 更好?因为在原来的情况下,每次调用test时都需要调用eval,而在这种用法中,eval在定义test时只调用一次;当test 被调用时,没有eval 完成。因此,虽然您可以在“应用程序运行时获取用户输入”的意义上调用eval“在运行时”,但在使用该用户输入构造的函数时,它不会被称为“在运行时”。叫。前者很好,而后者显然是一种反模式。

    【讨论】:

    • 我不断看到人们这样说(也在 JavaScript 社区中)。我编写了很多开发工具,例如在运行时评估用户代码的代码,并尽我所能尝试,如果不在运行时使用 eval,我无法弄清楚如何做这些事情。我还为 JavaCall 贡献了代码,该代码在运行时使用 eval 并结合 Java 在运行时的自省来生成调用 Java 的函数,如果不在运行时使用 eval,我看不到这样做的好方法。也许我遗漏了一些东西,但“运行时评估是一种反模式”的笼统声明对我来说似乎没有根据。
    • 我已经扩展了我的答案以改进它。感谢您提示我这样做,原来的答案太简洁了,不是很有帮助。希望这会更好。
    【解决方案2】:

    正如@StefanKarpinski 提到的eval 总是在全局范围内评估,但如果一个人真的想在本地评估某些东西,有多种方法可以做到:

    import Base.Cartesian.lreplace
    i = 50
    function test1(expr)
      i=10
      eval(lreplace(expr,:i,i))
    end
    
    i = 50
    function test2()
      i = 10
      @eval $i
    end
    test1(:(i))  # => 10
    test2()      # => 10
    

    但我更喜欢在运行时评估表达式的方法是创建一个函数,我认为这是最有效的:

    exprtoeval=:(x*x)
    @eval f(x)=$exprtoeval
    f(4) # => 16
    

    【讨论】:

      【解决方案3】:

      根据应用程序,您可以eval 整个函数以获取i 的本地值,例如@simonster 在this answer 中描述。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-29
        • 2021-05-02
        相关资源
        最近更新 更多