Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 类型::微小而深刻的强制_Perl_Moo - Fatal编程技术网

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,
);