在 Julia 函数作用域内的 if 语句内定义函数的错误结果

问题描述 投票:0回答:1

我觉得有点奇怪,它在全局范围内工作得很好,但在函数作用域内,编译器诉诸于在

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

但是,似乎这在函数作用域中无法可靠地工作。

function if-statement scope julia compiler-warnings
1个回答
0
投票

正如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
条件通常也可以被优化(由于编译器中的不断传播),但不能保证总是如此,因此通常最好基于类型而不是值来制定这样的条件论点。

© www.soinside.com 2019 - 2024. All rights reserved.