Search code examples
perlmoosemoops

Can someone please explain how to implement and utilize privately-scoped arrays in Moops?


I am trying to learn Moops and I can't quite grasp how to use populate and iterate over lexical_has arrayRefs. Can you demonstrate their usage here with code please?

I wrote the following:

lexical_has people => (is => 'rw', 
                       isa => ArrayRef, 
                       default => sub { [] }, 
                       accessor => \(my @people), 
                       required => 0);

I tried to populate it thusly:

$self->$people[$counter](Employee->new()->dispatch());

But it keeps error-ing on me "Syntax error near >$people[]"


Solution

  • You are setting accessor => \@people which shows a fundamental misunderstanding of what lexical_has does. lexical_has installs a coderef into that variable, so it ought to be a scalar.

    So, once you have $people as a scalar, which lexical_has has installed a coderef into, then $self->$people() or $self->$people is a method call which returns an arrayref. Thus @{ $self->$people } is the (non-ref) array itself, which you can use for push/pop/shift/unshift/grep/map/sort/foreach/etc.

    Quick example:

    use Moops;
    
    class GuestList {
    
      lexical_has people => (
        isa      => ArrayRef,
        default  => sub { [] },
        reader   => \(my $people),
        lazy     => 1,
      );
    
      method add_person (Str $name) {
        push @{ $self->$people }, $name;
      }
    
      method announce () {
        say for @{ $self->$people };
      }
    
    }
    
    my $list = GuestList->new;
    $list->add_person("Alice");
    $list->add_person("Bob");
    $list->add_person("Carol");
    $list->announce;
    

    Output is:

    Alice
    Bob
    Carol
    

    Here is the equivalent code using a public attribute for people...

    use Moops;
    
    class GuestList {
    
      has people => (
        is       => 'ro',
        isa      => ArrayRef,
        default  => sub { [] },
        lazy     => 1,
      );
    
      method add_person (Str $name) {
        push @{ $self->people }, $name;
      }
    
      method announce () {
        say for @{ $self->people };
      }
    
    }
    
    my $list = GuestList->new;
    $list->add_person("Alice");
    $list->add_person("Bob");
    $list->add_person("Carol");
    $list->announce;