cod*_*ons 10 exception rakudo compile-time raku
是否可以CONTROL从特征中添加移相器?
按照docs 中的示例,在运行时代码中添加自定义控件异常很简单:
class CX::Oops does X::Control {};
sub f { CONTROL { when CX::Oops { note 'Oops!'; .resume}}
CX::Oops.new.throw; }
f; # OUTPUT: «Oops»
Run Code Online (Sandbox Code Playgroud)
但是,我尝试从特征中这样做并没有奏效:
sub trait_mod:<is>(Sub $fn, :$oopsable) {
$fn.add_phaser: 'CONTROL', { when CX::Oops { note 'Oops!'; .resume} }}
sub g is oopsable { CX::Oops.new.throw; }
g; # OUTPUT: «control exception without handler»
Run Code Online (Sandbox Code Playgroud)
从.has_phasers和fire_phasers(有趣的名字!)方法,我可以看出这是添加控制移相器。我需要做些什么来将其注册为处理程序,还是我还缺少其他东西?
这是一个有趣的问题,是否CATCH并且CONTROL真的是移相器。它们适合使用大写字母并对特定时间发生的事情做出反应。但是,它们也在语法的不同部分进行解析,作为语句控制,因此仅限于在语句级别发生。编译器也不会通过调用 来处理它们add_phasers。异常处理程序隐含了一些代码生成,并且是例程主体中生成的代码实际导致异常被处理。
人们可以合理地询问编译器是否不应该查看特征是否确实add_phasers使用CATCHor调用,CONTROL然后相应地生成代码。但是,由于在当前的编译器实现中,处理程序是例程主体的一部分,并且在调用 trait 处理程序之前在例程主体上完成了所有工作(优化除外),因此特性要生效为时已晚。
此外,CATCHandCONTROL块的主体不是简单地编译为普通块,而是生成处理when智能匹配的代码,如果没有处理程序匹配,则重新抛出异常;至少这最后一步需要手动完成。$!如果我没记错的话,还有一些关于更新的内容。
一个好消息是即将推出的rakuast基于编译器的前端将:
CATCH/CONTROL处理程序,从而获得所有正确的语义并执行与直接写入代码的语义相同的语义。