我觉得有点奇怪,它在全局范围内工作得很好,但在函数作用域内,编译器诉诸于在
ifelse
语句内定义一个函数,我将其显式设置为 false。
但是,有没有标准可以防止这种混乱,这种现象背后的底层编译逻辑是什么?
我不确定,但我想这个问题可能与Conditionally Define a function inside another function in Julia有关。
我进行了这个简单的实验。最初,我在全局范围内定义了实验,一切都按预期进行。但是,当我在函数作用域内运行相同的代码片段时,输出似乎受到
ifelse
语句的影响,尽管它被设置为 false。
# weird.jl
function experiment()
g(x) = 0
if ( true )
println("Here")
g(x) = 0
elseif (false)
g(x) = 1
end
println("We expect g(1) == 0, and we get g(1) ==", g(1))
end
g(x) = 0
if (true)
println("Here")
g(x) = 0
elseif (false)
g(x) = 1
end
println("We expect g(1) == 0, and we get g(1) ==", g(1))
println("\nExperiment")
experiment()
有输出
WARNING: Method definition g(Any) in module Main at /root/code/weird.jl:3 overwritten at /root/code/weird.jl:6.
WARNING: Method definition g(Any) in module Main at /root/code/weird.jl:6 overwritten at /root/code/weird.jl:8.
Here
We expect g(1) == 0, and we get g(1) ==0
Experiment
Here
We expect g(1) == 0, and we get g(1) ==1
关于申请。对我来说,总体目标是能够定义这样的函数
function lots_of_computations(mode)
# Defining variables and computations ....
if ( mode==Physical )
g_0(x, t) = 0
g_1(x) = 0
g_2(x,t) = 0
elseif (mode==General)
g_0(x, t) = 2*ε*sin(2π*t/(100*τ))*sin(2π*x[1]/L)*cos(2π*x[2]/L)
g_1(x) = ε*x[1]
g_2(x,t) = ε*t*x[2]
else
println("not supported")
end
# More computations ....
end
但是,似乎这在函数作用域中无法可靠地工作。
正如https://github.com/JuliaLang/julia/issues/15602中所解释的那样(在您看到的Conditionally Define a function inside another function in Julia中链接)当前推荐的安全方法实现你想要的就是使用匿名函数,这样你的代码就可以看起来例如喜欢:
function lots_of_computations(mode)
# Defining variables and computations ....
if mode isa Physical
g_0 = (x, t) -> 0
g_1 = x -> 0
g_2 = (x,t) -> 0
elseif mode isa General
g_0 = (x, t) -> 2*ε*sin(2π*t/(100*τ))*sin(2π*x[1]/L)*cos(2π*x[2]/L)
g_1 = x -> ε*x[1]
g_2 = (x,t) -> ε*t*x[2]
else
println("not supported")
end
# More computations ....
end
请注意,我将
mode==Physical
更改为 mode isa Physical
,以便条件基于 mode
的类型而不是其值。原因是在这种情况下,if
语句将在编译期间被优化。 mode==Physical
条件通常也可以被优化(由于编译器中的不断传播),但不能保证总是如此,因此通常最好基于类型而不是值来制定这样的条件论点。