我在驼鹿课上有以下几个方面

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') ]

09-11 08:57
查看更多