我在Moose课上有以下特性
package myPackage;
use Moose;
has Number => (
is => 'rw',
isa => Num,
);
是否有一个选项与Moose约束此类型浮点数从0到100如果有人试图插入数字不在0 -100的范围,那么值将是undef,如果是,我怎么能实现它?
最佳答案 这似乎按照要求做了……
{
package MyPackage;
use Moose;
use Types::Standard qw( Maybe Num );
use Types::Numbers qw( NumRange );
has n => (
is => 'rw',
isa => (Maybe[ NumRange[0,100] ])->plus_coercions(Num, sub { undef }),
coerce => 1,
);
}
print MyPackage->new( n => 99 )->dump;
print MyPackage->new( n => 100 )->dump;
print MyPackage->new( n => 101 )->dump;
更新:一些解释……
这是0到100之间的数字的类型约束:
NumRange[0,100]
用Maybe […]包装它允许将undef作为值接受:
Maybe[ NumRange[0,100] ]
现在我们需要在该表达式返回的类型约束对象上调用一个方法.由于 – >的优先级,“明显的”Maybe […] – > methodname将无效. operator(它会尝试在arrayref上调用该方法,并将结果传递给Maybe).所以我们需要提供一些括号来进行方法调用(Maybe […]) – > methodname.
我们将调用的方法是plus_coercions,在Type::Tiny中定义(Types :: Standard和Types :: Numbers使用的基础类型约束库).这会创建一个新的子类型[NumRange [0,100]],但会为其添加一些强制.
我们增加的强制是:
Num, sub { undef }
…这意味着“如果要强制的值是一个数字,则运行此子并使用其输出”.在sub中,我们不需要检查被强制的值是否在0..100范围之外,因为只有当值失败了Maybe [NumRange [0,100]]类型约束时才会触发强制.
事实上,我们也可以这样表达:
(Maybe[ NumRange[0,100] ])->plus_coercions(Num, 'undef')
…使用一串Perl代码而不是sub.这可能稍微不那么清楚,但可能会稍微快一点,因为它允许Type :: Tiny使用内联代码来玩弄技巧. (通过它我基本上意味着连接Perl代码的各种字符串并对它们进行评估,这样它最终会得到一个完成检查/强制执行的子程序,而不需要调用不同的子程序来执行检查和强制执行.)
在这种情况下,它不太可能对性能产生任何可察觉的差异,但是如果您想要强制执行此类数字的大量数据,您可能会注意到.
ArrayRef[ (Maybe[NumRange[0,100]])->plus_coercions(Num, 'undef') ]