Exception 在CATCH块[RAKU]中区分异常和故障

Exception 在CATCH块[RAKU]中区分异常和故障,exception,try-catch,raku,Exception,Try Catch,Raku,我们知道故障可以通过CATCH块来处理 在下面的示例中,我们创建了一个“临时”故障(在其他子系统中),并在CATCH块(在我的子系统中)中处理异常 输出如下: AdHoc Exception handled here This was a Failure 我的问题是:我们如何在CATCH块中区分失败和“正常”异常,以便区分这两种情况?失败和异常之间的关系是故障有一个异常——也就是说,它保存异常对象作为其状态的一部分。大概是这样的: class Failure { has Excepti

我们知道故障可以通过CATCH块来处理

在下面的示例中,我们创建了一个“临时”故障(在其他子系统中),并在CATCH块(在我的子系统中)中处理异常

输出如下:

AdHoc Exception handled here
This was a Failure

我的问题是:我们如何在CATCH块中区分失败和“正常”异常,以便区分这两种情况?

失败和异常之间的关系是故障有一个异常——也就是说,它保存异常对象作为其状态的一部分。大概是这样的:

class Failure {
    has Exception $.exception;
    # ...
}
当一个
故障
发生“爆炸”时,它会通过抛出其内部的
异常来进行爆炸。因此,到达
CATCH
块的是
异常
对象,并且没有返回到封闭的
故障
的链接。(事实上,一个给定的
异常
对象原则上可以由许多
故障
s持有。)

因此,没有直接的方法来检测这一点。从设计的角度来看,您可能不应该这样做,并且应该找到一种不同的方法来解决您的问题。
失败
只是一种延迟异常抛出并允许将其作为值处理的方法;根本问题的本质不会改变,因为它是作为一种价值而不是控制流的即时转移来传递的。不幸的是,问题中没有说明最初的目标;您可能会发现查看控件异常很有用,但也可能会发布另一个关于您试图解决的潜在问题的问题。也许有更好的办法

为了完整起见,我将注意到有一些间接的方法可以检测到
异常
是由
故障
引发的。例如,如果获取异常对象的
.backtrace
,并查看顶部帧的包,则可以确定它来自
故障

sub foo() { fail X::AdHoc.new(message => "foo") }
try {
    foo();
    CATCH {
        note do { no fatal; .backtrace[0].code.package ~~ Failure };
        .resume
    }
}

但是,这在很大程度上取决于易于更改的实现细节,因此我不会依赖它。

只需删除
试试
包装器:

sub my-sub {

#    try {              <--- remove this line...

        CATCH {
            when X::AdHoc { say 'AdHoc Exception handled here'; .resume }
            default {say 'Other Exception'; .resume}
        }

        my $b = other-sub();

        $b.so ?? $b.say !! 'This was a Failure'.say;

#    }                  <--- ...and this one

}

sub other-sub { fail 'Failure_X' }

my-sub();
sub我的sub{

#试着{澄清一下,我的意图是只处理异常(在CATCH块中)。如果发生故障,我希望恢复,就好像什么都没发生一样,让其余的代码(在CATCH之外)处理失败。在我的示例中,我没有料到返回的失败会触发包含的异常!我所做的只是在$b中获取结果并将其作为Bool进行检查。在我看来,这并不构成“使用”失败,因此触发CATCH块!相反,CATCH似乎总是在处理失败中包含的异常!!此外,在您的示例中,关于检测失败的间接方法,返回的Bool(来自智能检查失败类型)的值为“False”。但我希望它为“True”!我错过了什么吗?@jakar A
try
块意味着
使用fatal
pragma,这意味着从块中进行的调用返回的任何
失败
都会立即转换为异常。只是不要使用
try
;一个
CATCH
可以进入Raku的任何块中(因此,只需在
sub
级别上使用它即可)。或者,在
try
块的顶部写入
no fatal
。那么我的第二条评论呢?运行我给出的示例可以在本地的Rakudo版本上打印
True
。如果在您的代码块上没有,这正好证明了这样做的脆弱性。
sub my-sub {

#    try {              <--- remove this line...

        CATCH {
            when X::AdHoc { say 'AdHoc Exception handled here'; .resume }
            default {say 'Other Exception'; .resume}
        }

        my $b = other-sub();

        $b.so ?? $b.say !! 'This was a Failure'.say;

#    }                  <--- ...and this one

}

sub other-sub { fail 'Failure_X' }

my-sub();