我在 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
由于 ->
的优先级,将无法工作运算符(它会尝试调用 arrayref 上的方法,并将结果传递给 Maybe
)。所以我们需要提供一些括号来做方法调用(Maybe[...])->methodname
.我们将调用的方法是
plus_coercions
,定义于 Type::Tiny (Types::Standard 和 Types::Numbers 使用的底层类型约束库)。这将创建一个新的子类型 Maybe[NumRange[0,100]]
但添加了一些强制。我们添加的强制是:
Num, sub { undef }
...这意味着“如果要强制的值是一个数字,则运行此子程序并使用其输出”。在 sub 中,我们不需要检查被强制转换的值是否在 0..100 范围之外,因为只有当值不符合
Maybe[NumRange[0,100]]
时才会触发强制转换。类型约束。其实我们也可以这样表达:
(Maybe[ NumRange[0,100] ])->plus_coercions(Num, 'undef')
... 使用一串 Perl 代码而不是子代码。这可能不太清楚,但可能运行得稍微快一点,因为它允许 Type::Tiny 使用内联代码玩花招。 (我基本上是指将各种 Perl 代码字符串和
eval
连接起来,以便最终可以得到一个执行整个检查/强制转换的子程序,而不需要调用不同的子程序来执行检查和强制转换.)在这种情况下,它不太可能对性能产生任何可察觉的差异,但是如果您有大量想要强制转换的此类数字的数组引用,您可能会注意到。
ArrayRef[ (Maybe[NumRange[0,100]])->plus_coercions(Num, 'undef') ]
关于perl - Moose 和约束类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20708347/