Perl 类型::微小而深刻的强制
我正在尝试使用Perl 类型::微小而深刻的强制,perl,moo,Perl,Moo,我正在尝试使用Type::Tiny进行深度强制,但没有成功。从历史上看,据说: “某些参数化类型约束可以自动获取 强制,如果其参数具有强制。例如: ArrayRef[Int->plus_强制(Num,q{Int($)})] ……这就是你的意思!” 我试图做到的是得到这样的“照我说的做”: 当使用Str元素实例化Family时,应自动将其强制为Person对象。我尝试了一系列不同的想法(加上强制、类型库等),但没有任何运气。他们都以同样的方式失败 使用加号强制时(从Str到Object) Type
Type::Tiny
进行深度强制,但没有成功。从历史上看,据说:
“某些参数化类型约束可以自动获取
强制,如果其参数具有强制。例如:
ArrayRef[Int->plus_强制(Num,q{Int($)})]
……这就是你的意思!”
我试图做到的是得到这样的“照我说的做”:
当使用Str
元素实例化Family
时,应自动将其强制为Person
对象。我尝试了一系列不同的想法(加上强制、类型库等),但没有任何运气。他们都以同样的方式失败
使用加号强制时(从Str
到Object
)
Type::Tiny引发异常:
Reference ["mom",bless( {"name" => "dad"}, 'Person' ),bless( {"name" =...] did not pass type constraint "ArrayRef[Object]" (in $args->{"members"})
"ArrayRef[Object]" constrains each value in the array with "Object"
"Object" is a subtype of "Object"
"Object" is a subtype of "Ref"
Value "mom" did not pass type constraint "Ref" (in $args->{"members"}->[0])
"Ref" is defined as: (!!ref($_))
我知道我可以通过使用Family
中的BUILDARGS
sub修改Family->new
的参数来解决这个问题,但是如果Type::Tiny可以自动完成这项工作,那就太好了
更新
多亏了托比的友好帮助,我才得以成功。唯一让我有点困扰的是使用了ArrayRef[Object]
而不是正确的ArrayRef[InstanceOf['Person']]
(InstanceOf
没有任何加上_强制
)。使用对象
可以将任何类的实例插入成员
,这当然不是您想要的
通过制作一个class\u类型
来解决这个问题。以下是完整的工作代码:
package Person;
use Types::Standard -types;
use Moo;
has name => (is => 'ro', isa => Str);
package Family;
use Types::Standard -types;
use Type::Utils -all;
use Moo;
my $Person = class_type { class => 'Person' };
my $Members = ArrayRef[
$Person->plus_coercions(Str, q{ Person->new(name => $_) })
];
has members => (
is => 'ro',
isa => $Members,
coerce => $Members->coercion,
);
sub list { join(', ', map { $_->name } @{ $_[0]->members }) }
package main;
my $family = Family->new(members => [
'mom',
Person->new(name => 'dad'),
Person->new(name => 'girl'),
'dog'
]);
print $family->list, "\n";
当运行时,会很好地打印妈妈、爸爸、女孩、狗。默认情况下,Moose/Moo/Mouse属性不会强制,因此即使类型约束有强制,您也需要告诉属性使用该强制 如果您使用的是驼鹿或鼠标,您可以执行以下操作:
has members => (
is => 'ro',
isa => ArrayRef[ Object->plus_coercions(Str, q{ Person->new(name => $_) }) ],
coerce => 1,
);
但是Moo不支持强制=>1
;相反,它期望coderef或重载对象充当强制。类型::Tiny可以通过调用$Type->impression
为您提供合适的重载对象
# Let's store the type constraint in a variable to avoid repetition...
my $type = ArrayRef[
Object->plus_coercions( Str, q{Person->new(name => $_)} )
];
has members => (
is => 'ro',
isa => $type,
coerce => $type->coercion,
);
InstanceOf
当然有加上强制
。但是,由于Perl运算符的优先级,执行“InstanceOf[“Person”]->加上强制(…)
将尝试在未禁用的arrayref上调用方法。它可以通过添加一些括号来分类:(InstanceOf[“Person”])->加上强制(…)
。当然了。无论如何,使用class\u类型
可以生成漂亮整洁的代码。ArrayRef[InstanceOf['Class::Name::Which::Is::Very::Long']
非常笨拙。但是知道不止一种方法是很好的。一如既往!
has members => (
is => 'ro',
isa => ArrayRef[ Object->plus_coercions(Str, q{ Person->new(name => $_) }) ],
coerce => 1,
);
# Let's store the type constraint in a variable to avoid repetition...
my $type = ArrayRef[
Object->plus_coercions( Str, q{Person->new(name => $_)} )
];
has members => (
is => 'ro',
isa => $type,
coerce => $type->coercion,
);