В Moose, как мне настроить сеттер arrayref?

#perl #moose

Вопрос:

У меня есть урок Лося, который

 has 'unique_ints' => (
    is              => 'rw',
    isa             => 'ArrayRef[Int]',
    default         => sub { [] },
);
 

Какой лучший способ гарантировать уникальность unique_int?

Ответ №1:

Атрибуты лося могут иметь trigger свойство, которое вызывается при каждом изменении этого атрибута. Свойство представляет собой ссылку на метод, которому передается объект, а также на новую и старую версии атрибута. Поэтому мы можем написать что-то вроде этого:

 package UniqInt;

use Moose;

use List::Util 'uniqint';

has 'unique_ints' => (
    is              => 'rw',
    isa             => 'ArrayRef[Int]',
    default         => sub { [] },
    trigger         => amp;_ensure_uniq,
);

sub _ensure_uniq {
  my $self = shift;
  my ($new) = @_;

  $self->{unique_ints} = [ uniqint @$new ];
}

1;
 

Обратите внимание, что в методе триггера мы используем прямой хэш-доступ к значению атрибута, так как повторный вызов мутатора снова вызовет метод триггера и приведет нас в бесконечную яму рекурсии.

Мы можем протестировать этот метод следующим образом:

 #!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use UniqInt;

my $obj = UniqInt->new;

$obj->unique_ints([1 .. 5]);

say join ',', @{$obj->unique_ints};

$obj->unique_ints([1 .. 5, 1 .. 5]);

say join ',', @{$obj->unique_ints};
 

Который, как и ожидалось, производит этот результат:

 1,2,3,4,5
1,2,3,4,5
 

Обновление: Обратите также внимание, что, поскольку я не использую третий параметр метода триггера (который является предыдущим значением атрибута), я игнорирую его.

Комментарии:

1. Альтернативным способом, если вы хотите избежать прямого доступа к хэш-ссылкам, было бы создать UniqArrayRef ограничение типа с принуждением от ArrayRef .