【发布时间】:2013-12-20 16:51:56
【问题描述】:
我在 Moose 类上有以下属性
package myPackage;
use Moose;
has Number => (
is => 'rw',
isa => Num,
);
Moose 是否有一个选项可以将此类型限制为从 0 到 100 的浮点数,如果有人尝试插入不在 0 -100 范围内的数字,那么该值将是 undef,如果是,我该如何实现?
【问题讨论】:
我在 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 并使用它的输出”。在 sub 中,我们不需要检查被强制的值是否在 0..100 范围之外,因为只有当值不符合 Maybe[NumRange[0,100]] 类型约束时才会触发强制。
其实我们也可以这样表达:
(Maybe[ NumRange[0,100] ])->plus_coercions(Num, 'undef')
... 使用 Perl 代码字符串而不是子代码。这可能不太清楚,但运行速度可能会稍微快一些,因为它允许 Type::Tiny 使用内联代码玩技巧。 (我的意思是连接各种 Perl 代码字符串并 evaling 它们,这样它就可以最终得到一个执行整个检查/强制的子程序,而不是需要调用不同的子程序来执行检查和强制.)
在这种情况下,它不太可能对性能产生任何可察觉的差异,但如果您有大量此类数字的数组引用,您想强制执行,您可能会注意到。
ArrayRef[ (Maybe[NumRange[0,100]])->plus_coercions(Num, 'undef') ]
【讨论】:
是的。请参阅 TypeConstraints 文档以及如何强制一个值。
【讨论】: