【发布时间】:2014-01-21 20:04:01
【问题描述】:
i = 50
function test()
i = 10
eval(:i)
end
test() # => 50
为什么这会评估为全局 i 而不是本地的?有没有办法让它评估到本地?
【问题讨论】:
标签: julia
i = 50
function test()
i = 10
eval(:i)
end
test() # => 50
为什么这会评估为全局 i 而不是本地的?有没有办法让它评估到本地?
【问题讨论】:
标签: julia
你不能。 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“在运行时”,但在使用该用户输入构造的函数时,它不会被称为“在运行时”。叫。前者很好,而后者显然是一种反模式。
【讨论】:
正如@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
【讨论】:
根据应用程序,您可以eval 整个函数以获取i 的本地值,例如@simonster 在this answer 中描述。
【讨论】: