#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
.