【问题标题】:Moose empty value for typed attributes类型化属性的驼鹿空值
【发布时间】:2013-07-09 03:00:57
【问题描述】:

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

例如,我正在编写一个链接列表的简单实现,并有一个 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 时:

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 类型。

有没有办法解决这个问题?

【问题讨论】:

    标签: perl moose


    【解决方案1】:

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

       has 'head' => (
          is      => 'rw',
          isa     => 'Maybe[Node]',
          # empty head node
          default => sub { 
             Node->new( value => undef, next => undef, prev => undef ); 
          }
       );
    
    【解决方案2】:

    下一个:

    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 表示基本层:

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

    稍后在TYPE UNIONS 部分中说:

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

    有'输出' => ( 是 => 'rw', isa => '对象 |文件句柄', );

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 哪些作者? (驼鹿的?)你能链接到你找到这个的地方吗?
      • 我只能找到Moose::Util::TypeConstraints manual 中的这条注释:“Undef 类型约束现在大部分都可以正常工作,但可能仍然存在边缘情况,请谨慎使用。”
      • @Hunter McMillen,来自 Moose,与我交流。也许在我提交的错误报告中?
      猜你喜欢
      • 1970-01-01
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多