我在驼鹿课上有以下几个方面
package myPackage;
use Moose;
has Number => (
is => 'rw',
isa => Num,
);
Moose是否有一个选项可以限制此类型以使数字从0 float 到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,您可能会注意到。
ArrayRef[ (Maybe[NumRange[0,100]])->plus_coercions(Num, 'undef') ]