捕捉并抛出自定义异常

Shn*_*son 7 perl6 raku

“ CATCH”是否应该在“ throw”之后严格调用?

范例1:

say 'Hello World!';

class E is Exception { method message() { "Just stop already!" } }

CATCH {
    when E {
            .resume;
    }
}

E.new.throw;
Run Code Online (Sandbox Code Playgroud)

错误:

找不到方法“接收器”:在/tmp/739536251/main.pl6第11行的块中没有方法缓存,也没有。^ find_method

范例2:

say 'Hello World!';

class E is Exception { method message() { "Just stop already!" } }

E.new.throw;

CATCH {
    when E {
            .resume;
    }
}
Run Code Online (Sandbox Code Playgroud)

没错

rai*_*iph 4

这是一个已经提交的.resume错误


该错误消息不是 P6 有史以来产生的最棒的消息,但从技术上讲它不是LTA,因为它是描述性的并且与错误(由 bu​​g 引起)相关。


CATCH 并抛出自定义异常

我认为这只是一个.resume错误,而不是关于自定义异常。

是否应该严格在“ throw”之后调用“ CATCH”?

不,这不是问题。(也就是说,将它放在.throwjust so 后面可以避免这个错误;稍后我会再讨论这个问题。)


在繁荣的代码中,您抛出一个异常,然后.resume对其做出响应。根据文档.resume

.throw从离开的地方恢复控制流

在本例中,这意味着箭头所指的位置:

E.new.throw ;
           
Run Code Online (Sandbox Code Playgroud)

现在,考虑这个程序:

42;
Run Code Online (Sandbox Code Playgroud)

如果你运行该程序你会看到:

Useless use of constant integer 42 in sink context (line 1)
Run Code Online (Sandbox Code Playgroud)

这是因为 Raku在决定在语句末尾做什么时应用“接收上​​下文”规则。应用接收器上下文需要调用.sink语句生成的值。并为该42方法.sink生成“无用”警告。

但是 d 抛出的异常有什么价值呢.resume

class E is Exception {}
CATCH { when E { .resume } }
say E.new.throw.^name; # BOOTException
E.new.throw.sink;      # Cannot find method 'sink':
                       # no method cache and no .^find_method
Run Code Online (Sandbox Code Playgroud)

事实证明,它BOOTException不是一个高级 Raku 对象,而是一个低级 VM 对象,一个没有.sink方法的对象(并且也阻碍了 P6 寻找方法的后备方法,因此“我尝试了一切”错误信息)。


那么为什么在投掷之后CATCH放置阻挡会产生不同的结果呢?

似乎只有当 throw 语句是最后一个语句时才会出现该错误。这工作正常,只是显示42

class E is Exception {}
CATCH { when E { .resume } }
E.new.throw;
say 42;
Run Code Online (Sandbox Code Playgroud)

您可能知道,Raku 特别对待块的最后一个语句。也许这个错误与此有关。