You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Raku的CATCH块中区分Failure与常规Exception的方法

如何在Raku的CATCH块中区分Failure与常规Exception

好问题!在Raku里,fail生成的Failure和直接抛出的常规Exception确实容易混淆——因为Failure被强制求值时会自动抛出对应的Exception(比如你例子里的X::AdHoc)。不过我们可以通过以下方法在CATCH块里精准区分两者:

核心思路:检查Exception的payload属性

当Failure被触发抛出Exception时,这个Exception的payload属性会保存原始的Failure对象;而直接用.throw抛出的常规Exception,它的payload一般是错误文本或自定义数据,不会是Failure类型。我们可以利用这一点做区分。

修改你的代码示例演示

我调整了你的代码,加入了常规Exception的测试,同时在CATCH块里做区分判断:

sub my-sub { 
    try { 
        CATCH { 
            when X::AdHoc { 
                # 检查当前Exception的payload是否为Failure
                if .payload ~~ Failure {
                    say 'AdHoc Exception from Failure handled here';
                    .resume;
                } else {
                    say 'Regular AdHoc Exception handled here';
                    .resume;
                }
            } 
            default {
                if .payload ~~ Failure {
                    say 'Other Exception triggered by Failure';
                } else {
                    say 'Other regular Exception';
                }
                .resume
            } 
        } 
        # 调用返回Failure的函数
        my $b = other-sub(); 
        $b.so ?? $b.say !! 'This was a Failure'.say; 

        # 主动抛出一个常规AdHoc Exception
        X::AdHoc.new(payload => 'Manual regular error').throw;
    } 
} 
sub other-sub { fail 'Failure_X' } 
my-sub();

运行输出:

AdHoc Exception from Failure handled here
This was a Failure
Regular AdHoc Exception handled here

补充:提前捕获Failure(非CATCH块场景)

如果你不需要等到CATCH块统一处理,也可以在获取函数返回值时直接判断是否为Failure类型,这样能更早处理:

my $b = other-sub();
if $b ~~ Failure {
    say "Got a Failure: $b.error";
    # 自定义处理逻辑
} else {
    # 正常使用返回值
}

这个方法更直接,但如果你的代码结构里必须在CATCH块统一处理异常,那么第一种检查payload的方式更适配你的需求。

内容的提问来源于stack exchange,提问作者jakar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:47:38