退出函数而不中止脚本

Sum*_*nal 8 rakudo raku

我有一个仅接受正值数组的函数。当给出任何负值时死亡。

# Consider edge cases
# First check if all elements are > 0, if not throw informative error
# Then if any of element is zero return 0
# Only else proceed further towards calculation


sub geometric_mean(@data) {
    if @data.any < 0 {die "Not possible to calculate geometric mean for negative values"};
    if @data.any == 0 { return 0 };
    my $sum;
    for @data {
        $sum += log($_);
    }
    return exp($sum/@data.elems)    
}
Run Code Online (Sandbox Code Playgroud)

如果我尝试运行脚本

my @data = [1, 2, 3.8, -1];
say geometric_mean(@data);

say "Hello world";
Run Code Online (Sandbox Code Playgroud)

代码在函数调用时退出而不运行最后一行,即不运行函数中的代码:

Not possible to calculate geometric mean for negative values
  in method throw at 'SETTING::'src/core.c/Exception.rakumod line 65
  in sub die at 'SETTING::'src/core.c/control.rakumod line 255
  in sub geometric_mean at c:\Users\suman\sum.p6 line 8
  in block <unit> at c:\Users\suman\sum.p6 line 20
Run Code Online (Sandbox Code Playgroud)

修改:

sub geometric_mean(@data) {
    if @data.any < 0 {die "Not possible to calculate geometric mean for negative values"};
    CATCH { default { warn "    Not possible to calculate geometric mean for negative values"; } };
    if @data.any == 0 { return 0 };
    my $sum;
    for @data {
        $sum += log($_);
    }
    return exp($sum/@data.elems)    
}
Run Code Online (Sandbox Code Playgroud)

现在也运行最后一行并输出:

    Not possible to calculate geometric mean for negative values
Nil
  in sub warn at 'SETTING::'src/core.c/control.rakumod line 269
Hello world
Run Code Online (Sandbox Code Playgroud)

此类情况如何处理?我查看了块,但这会执行我想避免的函数内try CATCH这些块下面的代码。

我经历过这个:

  1. 将抛出的异常更改为失败的简洁方法?
  2. https://docs.raku.org/routine/throw
  3. https://docs.raku.org/type/Exception
  4. https://dev.to/lizmat/exceptions-3g0i

Hov*_*uch 6

die用于致命异常。如果您想继续控制流,您不希望出现致命异常。

有两种方法可以解决这个问题。首先,使用fail代替die,然后检查调用是否失败with

sub geometric_mean(@data) {
    if @data.any < 0 {fail  "Not possible to calculate geometric mean for negative values"};
// etc
}

my @data = [1, 2, 3.8, -1];
with geometric_mean(@data) -> {} else {say .exception.message};

say "Hello world";
Run Code Online (Sandbox Code Playgroud)

另一种方法是根本不抛出异常,而是返回

sub geometric_mean(@data) {
    if @data.any < 0 {say  "Not possible to calculate geometric mean for negative values"; return};
// etc
}

my @data = [1, 2, 3.8, -1];
geometric_mean(@data);

say "Hello world";
Run Code Online (Sandbox Code Playgroud)


p6s*_*eve 3

我认为您在问“如何避免在失败或死亡时发出回溯详细信息?

如果是这样,您可以不生成异常,如下所示:

sub geometric_mean(@data) {
    if @data.any < 0 { return "Not possible to calculate geometric mean for negative values" }
    if @data.any == 0 { return 0 };
    my $sum;
    for @data {
        $sum += log($_);
    }   
    exp($sum/@data.elems)               
}

my @data = [1, 2, 3.8, -1];
say geometric_mean(@data);

say "Hello world";
Run Code Online (Sandbox Code Playgroud)
Not possible to calculate geometric mean for negative values
Hello world
Run Code Online (Sandbox Code Playgroud)

编辑:删除了我的推测性 try/CATCH 变体,因为每个评论都不好在同一块中使用 try 和 CATCH 。

  • 尽管我也想到,使用“{}”创建一个新作用域可能是一个更好的主意,因为它不会影响“CATCH”内部拼写错误的方法名称 (2认同)