如何从块的CATCH移相器返回值?

时间:2018-04-18 02:05:43

标签: perl6 raku rakudo

从不是例程的块中从CATCH移相器返回值的语法是什么?

sub foo() {
    <1 2 3>.map: -> $a {
        die 'oops';
        CATCH { default { 'foo' } }
    }
}

sub bar() {
    <1 2 3>.map: -> $a {
        die 'oops';
        CATCH { default { return 'bar' } }
    }
}

say foo(); # (Nil, Nil, Nil)
say bar(); # Attempt to return outside of immediatelly-enclosing Routine (i.e. `return` execution is outside the dynamic scope of the Routine where `return` was used)

编辑:所需的输出是:

say baz(); # (baz baz baz)

用例是map Seq一个方法,它间歇性地抛出异常,通过返回默认值来处理传递给map的块内的异常。

2 个答案:

答案 0 :(得分:8)

返回退出功能范围,但在bar()中使用它的方式有两种功能在起作用。

  1. bar()方法本身。
  2. 你在里面嵌入了返回的lambda。
  3. 这意味着你的回归含糊不清(好吧,至少对某些人而言),编译器会不肯。

    没有&#34;返回&#34; foo()中的值作为块内的常量处理,块返回Nil。这意味着在foo()中,您有效地避免了解析return的含义,有效地在堆栈上推送Nil

    这就是为什么在Nil的捕获输出中有3个foo() s的原因。对于bar(),目前还不清楚您是否希望在第一个抛出的异常上终止执行bar()例程,或者您是否只想将'bar'作为非Nil传递回去将CATCH块压入堆栈。

    代码的略微修改版

    #!/bin/env perl6
    
    sub foo() {
        <1 2 3>.map: -> $a {
            die 'oops';
        }
        CATCH { default { 'foo' } }
    }
    
    sub bar() {
        <1 2 3>.map: -> $a {
            die 'oops';
        }
        CATCH { default { return 'bar' } }
    }
    
    say foo();
    
    say bar();
    

    可能会使这一点更加明确。它的输出是

    [edwbuck@phoenix learn_ruby]$ ./ed.p6 
    Nil
    bar
    

答案 1 :(得分:3)

这里发生的是懒惰列表导致控制流不明显。

你的两个函数的返回值是一个Seq,它的值是通过依次调用值a,b和c上的小lambda生成的。知道了这一点,就很容易理解为什么你不能改变bar的返回值:bar已经在你的lambda第一次被调用之前已经返回了。列表为say d后,将生成所有值并抛出异常。

获得所需内容的正确方法是在地图结果上调用.eager,从而在函数返回之前评估整个列表,这样您就可以使用return来更改值bar返回。