我们使用Perl。
让我们定义一组属性:
package C;
use Moo;
use Types::Standard qw(Str Int Num Maybe);
has 'x' => (is=>'rw', isa=>Str);
has 'y' => (is=>'rw', isa=>Int);
has 'z' => (is=>'rw', isa=>Int);
# here to insert make_optional() described below
1;我想写一个例程,它将用MaybeT代替T,用于某些属性。例如:make_optional(qw(x y))应该创建x Maybe[Str]类型和y Maybe[Int]类型。
怎么和Moo一起做?
发布于 2020-11-05 16:36:58
[[请注意,Maybe类型实际上并不使属性本身具有可选性,而是具有undef-容忍度)。默认情况下,Moo属性已经是可选的。但为了便于讨论,我将继续使用可选和必需的术语。]
因为我不喜欢“你不能”的回答,这是一些你想要的代码.
use strict;
use warnings;
BEGIN {
package MooX::MakeOptional;
use Types::Standard qw( Maybe Any );
use Exporter::Shiny our @EXPORT = qw( make_optional has );
use namespace::clean;
sub _exporter_validate_opts {
my $opts = pop;
$opts->{orig_has} = do {
no strict 'refs';
\&{ $opts->{into} . '::has' };
};
$opts->{attributes} = [];
'namespace::clean'->clean_subroutines( $opts->{into}, 'has' );
}
sub _generate_has {
my $opts = pop;
my $attributes = $opts->{attributes};
return sub {
my ( $name, %spec ) = @_;
if ( ref($name) eq 'ARRAY' ) {
push @$attributes, $_, { %spec } for @$name;
}
else {
push @$attributes, $name, \%spec;
}
};
}
sub _generate_make_optional {
my $opts = pop;
my $attributes = $opts->{attributes};
my $orig_has = $opts->{orig_has};
return sub {
my %optional;
$optional{$_} = 1 for @_;
while ( @$attributes ) {
my ( $name, $spec ) = splice( @$attributes, 0, 2 );
if ( $optional{$name} ) {
$spec->{isa} = Maybe[ $spec->{isa} or Any ];
}
$orig_has->( $name, %$spec );
}
}
}
}
{
package C;
use Moo;
use MooX::MakeOptional;
use Types::Standard qw( Str Int );
has 'x' => ( is => 'rw', isa => Str );
has 'y' => ( is => 'rw', isa => Int );
has 'z' => ( is => 'rw', isa => Int );
make_optional( qw(x y) );
}这样做是用一个虚拟替换替换Moo的has关键字,它只会将属性定义存储到数组中。
然后,当调用make_optional时,这将在数组中运行,并将每个属性定义传递给Moo的原始has关键字,但如果指定,则更改为可选。
use MooX::MakeOptional总是需要确保在类定义的末尾调用make_optional函数的类,即使它们没有可选属性。如果它们没有可选属性,则只需调用make_optional并将其传递给空列表。
发布于 2016-09-16 13:25:17
你不能.
Moo没有元对象协议。没有它,你就不能回去改变东西。
没有元对象。如果您需要这个级别的复杂性,您需要Moose很小,因为它没有显式地提供元协议。
此外,这些类型只是代码参考。
没有内置的类型系统。isa是用代码验证的;如果您需要复杂的类型,Type::Tiny可以提供类型、类型库,并且可以无缝地与Moo和Moose一起工作。
您可以做的是编写一种类型,访问其他地方的某个类型,以决定它的行为是否像Maybe[Str]或Str,但这是一个很长的时间,而且可能是丑陋和疯狂的,您不应该这样做。
https://stackoverflow.com/questions/39532429
复制相似问题