Moose(Perl):将undef转换为空字符串或0而不是die()

时间:2011-06-23 16:57:43

标签: perl undefined moose

由于不完整的数据被提供给我的Moose构造函数,我从QA收到了很多异常。属性名称存在于构造函数参数中,但值为undef

许多脚本应用程序都是事实,事情只是undef。而且这通常很好。你不希望来自warnings pragma的恼人警告(所以你做no warnings 'uninitialized'),你肯定不希望你的代码死掉,因为一个小的值,比如housenumber,是{{ 1}}。

所以不用多说,我希望我的Moose构造函数表现得像直接Perl(即没有undef),即将use warnings 'uninitialized'转换为undef或根据需要转换为空字符串。此示例中显示的尝试不适用于存在属性名称但值为0的情况。我可以考虑使用undef来实现我想要的。但是在没有resorting to MooseX::UndefTolerant的普通Moose中是否有一种声明性的方式(遗憾的是我不能使用它,因为它没有安装)?

BUILDARGS

3 个答案:

答案 0 :(得分:9)

Moose::Manual::Types中,记录的方式可以解决这类问题。

使用Maybe[a]类型。

package AAA;
use Moose;

has 'hu', is => 'ro', isa => 'Str';
has 'ba', is => 'ro', isa => 'Int';

no Moose; __PACKAGE__->meta->make_immutable;


package BBB;
use Moose; extends 'AAA';

has 'hu', is => 'rw', isa => 'Maybe[Str]', default => ''; # will not die on undef
has 'ba', is => 'rw', isa => 'Maybe[Int]', default => 0;  # idem

sub BUILD {
    my $self = shift;
    $self->hu('') unless defined $self->hu;
    $self->ba(0) unless defined $self->ba;
}

no Moose; __PACKAGE__->meta->make_immutable;


package main;
use Test::More;
use Test::Exception;

# Those AAAs should die ...
throws_ok { AAA->new( hu => undef ) }
    qr/Validation failed for 'Str' with value undef/;
throws_ok { AAA->new( ba => undef ) }
    qr/Validation failed for 'Int' with value undef/;

# .. but these BBBs should live:
lives_ok  { BBB->new( hu => undef ) } 'hu supplied as undef';
lives_ok  { BBB->new( ba => undef ) } 'ba supplied as undef';

my $bbb = BBB->new( hu => undef, ba => undef );

is $bbb->hu, '', "hu is ''";
is $bbb->ba, 0, 'ba is 0';

done_testing;

答案 1 :(得分:4)

你的抱怨确实是穆斯正在做的事情正是应该做的。如果您明确地将undef作为值传递,但该值只能是Int,那么您应该收到错误。

所以你需要做出选择。您可以更改类型(通过union)以允许undef作为有效值,如下所示:

    has 'hu', is => 'ro', isa => 'Str | Undef';
    has 'ba', is => 'ro', isa => 'Int | Undef';

或者您可以不发送未定义的值:

    my %aa_params = ();
    $aa_params{hu} = $foo if defined $foo;

    $aa = AA->new( %aa_params );

或者最后,由于一些未知的原因,你绝对无法拒绝为不应该明确设置为undefined的事物发送无效的未定义值,只需写一个快速过滤器:

    sub filt_undef {
      my %hash = @_;
      return map { $_ => $hash{$_} } grep { defined $hash{$_} } keys %hash;
    }

    $aa = AA->new( filt_undef( hu => undef ) );

但这看起来很尴尬和可怕。

答案 2 :(得分:2)

或使用即时强制:

package BBB;
use Moose;
use MooseX::AttributeShortcuts;
extends 'AAA';
has '+hu',
  traits => [Shortcuts],
  coerce => [ Undef => sub { '' } ],
;