类型属性的驼鹿空值

时间:2013-07-08 18:34:23

标签: perl moose

在Moose中是否有某种方式指定我希望某个属性具有特定类型,但也允许存在空值(undef?)。

例如,我正在编写一个链接列表的简单实现,并且有一个Node类,其中nextprev指针必须是Node类型(这可能是什么你会期待的)

package Node;
{
   use Moose; 

   has 'value' => (
      is  => 'rw',
      isa => 'Any', # Nodes can be of any type
   );

   has 'prev' => (
      is        => 'rw',
      isa       => 'Node',
      predicate => 'has_prev',
   );

   has 'next' => (
      is        => 'rw',
      isa       => 'Node',
      predicate => 'has_next',
   );

}

但是我希望使用存储在列表头部的标记空节点来标记头部,而不是列表的实际元素。所以元素列表[1,2,3]实际上看起来像是:

EMPTY -> 1 -> 2 -> 3

我希望能够为nextprev指针指定一个空值(例如undef),但是当我在List类中创建一个空Node时:< / p>

package List;
{
   use Moose;

   has 'head' => (
      is      => 'rw',
      isa     => 'Node',
      # empty head node
      default => sub { 
         Node->new( value => undef, next => undef, prev => undef ); 
      }, 
   );

Moose抱怨因为undef不属于Node类型。

有解决方法吗?

3 个答案:

答案 0 :(得分:5)

您可以使用Maybe[type]语法来允许类型或undef。以你的例子:

   has 'head' => (
      is      => 'rw',
      isa     => 'Maybe[Node]',
      # empty head node
      default => sub { 
         Node->new( value => undef, next => undef, prev => undef ); 
      }
   );

答案 1 :(得分:1)

下一个:

use 5.014;
use warnings;

package Node {
   use Moose; 
   has 'value' => ( is  => 'rw');
   has 'prev' => ( is => 'rw', isa => 'Undef|Node', predicate => 'has_prev', default=>undef );
   has 'next' => ( is => 'rw', isa => 'Undef|Node', predicate => 'has_next', default=>undef );
}

package List {
   use Moose;
   has 'head' => ( is => 'rw', isa => 'Node', default => sub { Node->new() } );
}

package main;
use Data::Dumper;

my $list = List->new();
say Dumper $list;

打印:

$VAR1 = bless( {
                 'head' => bless( {
                                    'next' => undef,
                                    'prev' => undef
                                  }, 'Node' )
               }, 'List' );

Moose::Manual::Types对于基本的hier说:

      Undef     <---- undefined
      Defined
          Value
              Str
                  Num
                      Int
                  ClassName <---- Class name
                  RoleName

以及后面的TYPE UNIONS部分说:

  

Moose允许您说某个属性可以是两个或更多   不同的类型。例如,我们可能允许使用Object或FileHandle:

     

有'output'=&gt; (         是=&gt; 'RW',         isa =&gt; '对象| FileHandle',);

正如其他人已经说过的,这里也是Maybe[Something],我不知道什么是更好的,但Something | SomethingOther看起来更像“perlish”(恕我直言)。 ;)

答案 2 :(得分:0)

作者更喜欢Undef|Node而不是Maybe[Node]

has 'prev' => (
   is        => 'rw',
   isa       => 'Undef|Node',
   predicate => 'has_prev',
);