从特性控制移相器

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_phasersfire_phasers(有趣的名字!)方法,我可以看出这添加控制移相器。我需要做些什么来将其注册为处理程序,还是我还缺少其他东西?

Jon*_*ton 9

这是一个有趣的问题,是否CATCH并且CONTROL真的是移相器。它们适合使用大写字母并对特定时间发生的事情做出反应。但是,它们也在语法的不同部分进行解析,作为语句控制,因此仅限于在语句级别发生。编译器也不会通过调用 来处理它们add_phasers。异常处理程序隐含了一些代码生成,并且是例程主体中生成的代码实际导致异常被处理。

人们可以合理地询问编译器是否不应该查看特征是否确实add_phasers使用CATCHor调用,CONTROL然后相应地生成代码。但是,由于在当前的编译器实现中,处理程序是例程主体的一部分,并且在调用 trait 处理程序之前在例程主体上完成了所有工作(优化除外),因此特性要生效为时已晚。

此外,CATCHandCONTROL块的主体不是简单地编译为普通块,而是生成处理when智能匹配的代码,如果没有处理程序匹配,则重新抛出异常;至少这最后一步需要手动完成。$!如果我没记错的话,还有一些关于更新的内容。

一个好消息是即将推出的rakuast基于编译器的前端将:

  1. 在特征处理程序中为例程的 AST 提供 API。然后可以使用它在 AST 级别添加CATCH/CONTROL处理程序,从而获得所有正确的语义并执行与直接写入代码的语义相同的语义。
  2. 将代码生成延迟到更晚,以便时间也能解决。

  • 有趣的!我刚刚假设 `add_phaser` 只让我添加现有的移相器之一,但你的回答让我意识到它允许任何事情: `&amp;f.add_phaser('NOPE', {say 42})` 是完全有效的。然后 `&amp;f.phasers('NOPE')[0]()` 调用关联的移相器。因此,“add_phaser”本质上允许我添加任意块作为子周围的元数据。迷人! (4认同)