Is there a Hash::Util alternative for compound hashes?
Asked Answered
A

5

5

I have a compound hashref as follows

my $ch = {
    k1 => [ { k=>1 }, { m=>2 } ],
    k2 => [ { l=>90}, ... ],
};

Hash::Util::lock_hashref_recurse($ch) does not effectively lock these values..

@{$ch->{k1}}[0]->{k} = 'New value'; is allowed ! How do i lock such a hashref completely ?

Askwith answered 5/8, 2013 at 11:30 Comment(0)
D
5

According to the documentation:

This method only recurses into hashes that are referenced by another hash. Thus a Hash of Hashes (HoH) will all be restricted, but a Hash of Arrays of Hashes (HoAoH) will only have the top hash restricted.

And you have a Hash of Arrays of Hashes

Diphosgene answered 5/8, 2013 at 11:36 Comment(1)
Okay, is there another way to lock such hashes ?? (other than Hash::Util)Askwith
C
2
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 …
Clementineclementis answered 5/8, 2013 at 14:6 Comment(0)
S
1

Hash::Util itself provides you a low-level function that you can replicate in Perl without XS functionality: i.e. lock_hash / lock_hashref. The rest of functionality you need is a simple hash traversal and can be easily implemented manually. Traverse through nested references while keeping list of visited ones and list of found hashes and then run loop over that found list with lock_hashref.

Semiprofessional answered 5/8, 2013 at 12:39 Comment(0)
I
0

There is Const::Fast, which is able to make any Perl variable completely read-only.

You won't get the die-on-read behaviour of Hash::Util when you try to read a non-legal key though.

Inductee answered 5/8, 2013 at 15:2 Comment(0)
D
0

What about Readonly?

E.g.

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";

gives

old value: '1'
Modification of a read-only value attempted at readonly.pl line 7

Note that %h3 is a hash, not a hashref. Hashrefs don't work well with 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";

gives

old value: '1'
new value: 'New value'
Delozier answered 25/12, 2013 at 6:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.