如何在Julia中计算局部变量
为什么该值计算为全局如何在Julia中计算局部变量,julia,Julia,为什么该值计算为全局i,而不是本地值?有没有办法让它在当地进行评估?你不能。Julia的eval总是对当前模块的作用域而不是本地作用域进行代码计算。在本地范围内调用eval是一种反模式和性能杀手。但是,您可以构造一个新函数,其中包含一点引用本地范围的用户代码,然后调用该函数。例如: i = 50 function test() i = 10 eval(:i) end test() # => 50 现在您可以调用test: # user-supplied expression e
i
,而不是本地值?有没有办法让它在当地进行评估?你不能。Julia的eval
总是对当前模块的作用域而不是本地作用域进行代码计算。在本地范围内调用eval
是一种反模式和性能杀手。但是,您可以构造一个新函数,其中包含一点引用本地范围的用户代码,然后调用该函数。例如:
i = 50
function test()
i = 10
eval(:i)
end
test() # => 50
现在您可以调用test
:
# user-supplied expression
expr = :(i^2 + 1)
# splice into function body
test = @eval function ()
i = 10
$expr
end
为什么这比在问题中调用
test
内部调用eval
要好?因为在最初的用法中,eval
需要在每次调用test
时调用,而在这种用法中,eval
在定义test
时只调用一次;调用test
时,不执行eval
。因此,虽然您可以调用eval
“在运行时”,意思是“当您的应用程序正在运行时,获取用户输入”,但在调用使用该用户输入构造的函数时,它不会被称为“在运行时”。前者很好,而后者显然是一种反模式。根据应用程序,您可以eval
整个函数以获得i
的局部值,如@simonster在中所述。如@StefanKarpinski所述eval
始终在全局范围内计算,但如果一个人真的想在当地评估某件事,有多种方法:
julia> test()
101
但我更喜欢在运行时计算表达式的方法是创建函数,我认为这是最有效的方法:
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
我一直看到人们这样说(在JavaScript社区也是如此)。我编写了很多开发工具,比如在运行时评估用户代码的代码,并尽可能地尝试,如果不在运行时使用eval,我就无法理解如何做这些事情。我还为JavaCall提供了代码,该代码在运行时使用eval,并结合Java在运行时的内省来生成调用Java的函数,如果不在运行时使用eval,我看不到一个好方法。也许我遗漏了一些东西,但“运行时评估是一种反模式”的笼统说法对我来说似乎毫无根据。我已经扩展了我的答案以改进它。谢谢你提醒我这么做,原来的答案太简洁了,没有多大帮助。希望这样更好。
exprtoeval=:(x*x)
@eval f(x)=$exprtoeval
f(4) # => 16