关于if语句:如果我在Julia中遇到错误,如何跳到代码的特定部分

How do I skip to a certain part of my code if I encounter an error in Julia

我有一个"包装函数",可以接受输入,然后依次运行许多函数,最后输出结果。 一个简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function wrapper(a,b)
    c = first_function(a,b)
    d = second_function(c)
    if typeof(d) == Int64
        e = third_function(d)
        f = fourth_function(e)    
        g = fifth_function(f)
        try
            h = sixth_function(g)
        catch
            i ="this has failed"
        end
        i = seventh_function(h)
    else i ="this has failed"
    end

    return i
end

我要设置" if-else"语句或" try-catch"语句的函数列表中大约有5个不同的地方。"其他"部分和"捕获"部分始终在评估相同的事物。 在此示例中,您可以通过查看else和catch语句都执行i ="这已失败"来了解我的意思。

有没有办法我可以在函数代码的底部定义i ="此操作失败",并告诉julia跳至" else"或" catch"部分的这一行? 例如,我希望以上内容是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function wrapper(a,b)
    c = first_function(a,b)
    d = second_function(c)
    if typeof(d) == Int64
        e = third_function(d)
        f = fourth_function(e)    
        g = fifth_function(f)
        try
            h = sixth_function(g)
        catch
            <skip to line 10>
        end
        i = seventh_function(h)
    else <skip to line 10>
    end

    <line 10> i ="this has failed"
    return i
end

您可以在此SO帖子中使用@def宏。例如:

1
2
3
@def i_fail_code begin
  i ="this has failed"
end

然后您将执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function wrapper(a,b)
    c = first_function(a,b)
    d = second_function(c)
    if typeof(d) == Int64
        e = third_function(d)
        f = fourth_function(e)    
        g = fifth_function(f)
        try
            h = sixth_function(g)
        catch
            @i_fail_code
        end
        i = seventh_function(h)
    else @i_fail_code
    end
    return i
end

这个宏非常酷,因为即使它本质上只是复制/粘贴其定义中的内容,它甚至还会获得行号以纠正错误(即,它将把您发送到@def定义中的正确行)。


还要注意,您几乎永远都不想在Julia中测试变量的类型-您应该通过多次分派来处理它。


您得到了一些很好的字面答案,可以回答您的字面问题,但真正的问题是,为什么首先需要这样做?听起来这是一个非常糟糕的设计决定。本质上,您是在彻底改变方向盘!您正在尝试实现"子例程"方法,而不是"功能"方法。有充分的理由,几十年前子例程几乎消失了。您的问题本质上可以归结为"为朱莉娅(GOTO for Julia)"这一事实,应该是一个很大的危险信号。

为什么不只定义另一个处理您的"失败代码"的函数并调用它呢?您甚至可以在包装函数中定义fail函数;嵌套函数在julia中是完全可以接受的。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
julia> function outer()
         function inner()
           print("Hello from inner\
");
         end
         print("Hello from outer\
");
         inner();
       end
outer (generic function with 1 method)

julia> outer()
Hello from outer
Hello from inner

因此,在您的情况下,您可以简单地在包装函数内定义一个嵌套的handle_failure()函数,并在需要时调用它,仅此而已。

PS:抢占典型的"现代代码中GOTO有一些合法用途"注释:这不是其中之一。


Julia通过宏内置了goto支持,这可能是最简单的选择。所以像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function wrapper(a,b)
    c = first_function(a,b)
    d = second_function(c)
    if typeof(d) == Int64
        e = third_function(d)
        f = fourth_function(e)    
        g = fifth_function(f)
        try
            h = sixth_function(g)
        catch
            @goto fail
        end
        i = seventh_function(h)
    else
        @goto fail
    end
    return i
    @label fail
    i ="this has failed"
    return i
end