我是an already filed .resume bug。
错误消息不是 P6 产生的最棒的消息,但从技术上讲它不是 LTA,因为它是描述性的并且与错误相关(由错误引起)。
捕获并抛出自定义异常
我认为这只是一个 .resume 错误,而不是关于自定义异常。
应该在“throw”之后严格调用“CATCH”吗?
不,这不是问题。 (也就是说,把它放在.throw 之后恰好可以避免这个错误;我稍后再讨论。)
在蓬勃发展的代码中,你抛出一个异常,然后.resume 来响应它。根据文档.resume:
在.throw 离开的地方恢复控制流
在这种情况下表示箭头指向的位置:
E.new.throw ;
?
现在,考虑这个程序:
42;
如果你运行那个程序,你会看到:
Useless use of constant integer 42 in sink context (line 1)
这是因为 Raku 在决定语句末尾的操作时应用了"sink context" 规则。应用接收器上下文需要对语句产生的值调用.sink。对于42,.sink 方法会生成“无用”警告。
但是.resumed 抛出的异常的价值是什么?
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
原来它是一个BOOTException 对象,它不是一个高级 Raku 对象,而是一个低级 VM 对象,一个没有 .sink 方法的对象(并且还阻碍了 P6 查找方法,因此出现“我尝试了一切”错误消息)。
那么为什么将 CATCH 块放在 之后会有所不同?
似乎只有在 throw 语句是 last 语句时才会出现该错误。这工作正常,只显示42:
class E is Exception {}
CATCH { when E { .resume } }
E.new.throw;
say 42;
您大概知道,Raku 对块的最后一条语句进行了特殊处理。也许这个错误与此有关。