Search code examples
perlmoose

Moose empty value for typed attributes


Is there some way in Moose to specify that I want an attribute to have a specific type, but also allow there to be a null value (undef?).

For example I am writing a simple implementation of a Linked List and have a Node class where the next and prev pointers are required to be of type Node (this is probably what you would expect)

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

}

But I was hoping to use a sentinel, empty node stored at the head of the list to mark the head, instead of an actual element of the list. So a list of elements [1, 2, 3] would actually look like:

EMPTY -> 1 -> 2 -> 3

I was hoping to be able to specify a empty value (like undef) for the next and prev pointers, but when I create an empty Node in my List class:

package List;
{
   use Moose;

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

Moose complains because undef is not of type Node.

Is there a way around this ?


Solution

  • You can use the Maybe[type] syntax to allow the type or undef. For your example:

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