Есть ли альтернатива Hash::Util для составных хешей?
У меня есть составной Hashref следующим образом
my $ch = {
k1 => [ { k=>1 }, { m=>2 } ],
k2 => [ { l=>90}, ... ],
};
Hash::Util::lock_hashref_recurse($ch)
не эффективно блокирует эти значения..
@{$ch->{k1}}[0]->{k} = 'New value';
позволено! Как мне полностью заблокировать такой хэшреф?
5 ответов
Согласно документации:
Этот метод повторяется только в хешах, на которые ссылается другой хеш. Таким образом, хэш хэшей (HoH) будет ограничен, но хэш массивов хэшей (HoAoH) будет ограничен только верхним хешем.
И у вас есть хэш массивов хешей
use strictures;
use Hash::Util qw(lock_hash);
use Data::Visitor::Callback qw();
my $ch = {
k1 => [{k => 1}, {m => 2}],
k2 => [{l => 90},],
};
Data::Visitor::Callback->new(
hash => sub {
lock_hash %{ $_ };
return $_;
}
)->visit($ch);
$ch->{k1}[0]{k} = 'New value';
__END__
Modification of a read-only value attempted at …
Hash::Util
сама предоставляет вам низкоуровневую функцию, которую вы можете реплицировать в Perl без функциональности XS: lock_hash
/ lock_hashref
, Остальная функциональность, которая вам нужна, - это простой обход хеша, который может быть легко реализован вручную. Просматривать вложенные ссылки, сохраняя список посещенных и список найденных хэшей, а затем выполнить цикл по найденному списку с lock_hashref
,
Как насчет Readonly?
Например
use Readonly;
Readonly my %h3 => (
k1 => [ { k=>1 }, { m=>2 } ],
k2 => [ { l=>90}, ],
);
print "old value: '$h3{k1}->[0]->{k}'\n";
$h3{k1}->[0]->{k} = 'New value';
print "new value: '$h3{k1}->[0]->{k}'\n";
дает
old value: '1'
Modification of a read-only value attempted at readonly.pl line 7
Обратите внимание, что %h3
это хэш, а не хэшреф. Хешрефы плохо работают с Readonly:
use Readonly;
Readonly my $h2 => {
k1 => [ { k=>1 }, { m=>2 } ],
k2 => [ { l=>90}, ],
};
print "old value: '$h2->{k1}->[0]->{k}'\n";
$h2->{k1}->[0]->{k} = 'New value';
print "new value: '$h2->{k1}->[0]->{k}'\n";
дает
old value: '1'
new value: 'New value'
Существует Const:: Fast, который может сделать любую переменную Perl полностью доступной только для чтения.
Однако вы не получите поведение Hash::Util "умри при чтении" при попытке прочитать нелегальный ключ.