为什么Perl 6会为我的子集类型抛出X :: AdHoc异常?

bri*_*foy 8 types exception perl6

这是Perl 6中报告的错误:X :: AdHoc而不是X :: TypeCheck :: Binding with subset parameter,首次报告于2015年11月.


在玩我的Perl 6模块Chemisty :: Elements时,我遇到了一个我没想到的异常问题.

我定义了一个类型,ZInt它将数字限制在周期图表上找到的序数(我在这里伪造了一点).然后我使用该类型将参数约束到子例程.我希望得到某种X :: TypeCheck,但我得到了X :: AdHoc:

use v6;

subset ZInt of Cool is export where {
    state ( $min, $max ) = <1 120>;
    ( $_.truncate == $_ and $min <= $_ <= $max )
        or warn "Z must be between a positive whole number from $min to $max. Got <$_>."
    };

sub foo ( ZInt $Z ) { say $Z }

try {
    CATCH {
        default { .^name.say }
        }

    foo( 156 );
    }
Run Code Online (Sandbox Code Playgroud)

首先,我得到两次警告,这很奇怪:

Z必须介于1到120之间的正整数之间.<156>.在zint.p6第5行的块中,Z必须在从1到120的正整数之间.得到<156>.在块zint.p6第5行X :: AdHoc

但是,X::AdHoc当我宁愿人们知道它是类型错误时,我会得到类型.

我检查了如果没有warn并且X::AdHoc再次发生会发生什么:

subset ZInt of Cool is export where {
    state ( $min, $max ) = <1 120>;
    ( $_.truncate == $_ and $min <= $_ <= $max )
    };
Run Code Online (Sandbox Code Playgroud)

所以,我想我可以抛出自己的异常:

subset ZInt of Cool is export where {
    state ( $min, $max ) = <1 120>;
    ( $_.truncate == $_ and $min <= $_ <= $max )
        or X::TypeCheck.new.throw;
    };
Run Code Online (Sandbox Code Playgroud)

但是,我得到一个警告:

在字符串上下文中使用Any的未初始化值.^ name,.perl,.gist或.say可以根据需要对未定义的内容进行字符串化.

在这一点上,我不知道有什么抱怨.我认为其中一种方法需要我不提供的东西,但我没有看到任何关于文档中new或参数的参数throw.

如何在没有警告的情况下获得我想要的类型以及我的自定义文本?

zos*_*tay 3

不要抛出异常或发出警告。相反,你想失败:

subset ZInt of Cool is export where {
    state ( $min, $max ) = <1 120>;
    ( $_.truncate == $_ and $min <= $_ <= $max )
        or fail "Z must be between a positive whole number from $min to $max. Got <$_>."
};
Run Code Online (Sandbox Code Playgroud)

我相信这就是你的意图。因自己的异常而失败也很好,但 X::TypeCheck 有一个错误。它应该要求“操作”或提供合理的默认值,就像“得到”和“预期”一样。

subset ZInt of Cool is export where {
    state ( $min, $max ) = <1 120>;
    ( $_.truncate == $_ and $min <= $_ <= $max )
    or fail X::TypeCheck.new(
            operation => "type check",
            expected  => ::('ZInt'),
            got       => $_,
        );
};
Run Code Online (Sandbox Code Playgroud)