develooper Front page | perl.perl5.porters | Postings from March 2022

Tie::IxHash and Hash::Utils interaction

Thread Next
From:
Glenn Golden
Date:
March 5, 2022 14:01
Subject:
Tie::IxHash and Hash::Utils interaction
Message ID:
YiNtIeBSgKnxThQv@huh.zplane.com
Dear Porters,

Suppose one wishes to construct an immutable hash which always returns its
keys in presented order.  One obvious approach would be via Tie::IxHash
and the lock_hash() function from Hash::Util. But they don't seem to play
well together.  Examples below.

RTFMing/Googling did not yield anything suggesting that combining tied
hashes with other "overloaded" hash functionality (e.g. as provided by
Hash::Util) might be problematic, although I can appreciate why it might
be so.  So maybe these examples are just demonstrating moronity on my
part ("you shouldn't expect this sort of thing to work"). Or perhaps it's
a genuinely unexpected conflict that might be worthy of a bug report or 
a doc warning (in which case I will be happy to file it as such on github).

What say you?

Apologies if this is the wrong place for this question/issue.  If so, I'll
open an issue on github.

Thanks. (And as always, h/t for maintaining Perl5.)

Glenn Golden


#----------------------------------------------------------------------
# Example 1: lock_hash() seems to prevent tie()ing with Tie::IxHash.
#----------------------------------------------------------------------
use 5.034;
use warnings;
use strict;

use Hash::Util    qw / lock_hash hash_locked /;
use Tie::IxHash;

my %h;
%h = (one => 1, two => 2, three => 3, four => 4);

lock_hash(%h);
print "%h is " .  (hash_locked(%h) ? "locked\n" : "not locked\n");

#
# {key,value} pairs displayed in random order, as expected per Perl convention.
#
print "\nBefore assignment to \$h{five}:\n";
while (my ($k, $v) = each %h) { print "  $k => $v\n"; }

#
# Naive expectation (WRONG): Call to tie() should succeed, subsequent
# accesses will be displayed in presented order rather than random order.
#
# Observed behavior: Call to tie() fails: "Modification of read-only value".
#
tie(%h, 'Tie::IxHash');

while (my ($k, $v) = each %h) { print "$k => $v\n"; }
print "\n";



#----------------------------------------------------------------------
# Example 2: Tie::IxHash seems to defeat lock_hash() functionality 
#----------------------------------------------------------------------
use 5.034;
use warnings;
use strict;

use Hash::Util    qw / lock_hash hash_locked /;
use Tie::IxHash;

my %h;
tie(%h, 'Tie::IxHash');
%h = (one => 1, two => 2, three => 3, four => 4);

lock_hash(%h);
print "%h is " .  (hash_locked(%h) ? "locked\n" : "not locked\n");

#
# {key,value} pairs displayed in presented order, as expected per Tie::IxHash.
#
print "\nBefore assignment to \$h{five}:\n";
while (my ($k, $v) = each %h) { print "  $k => $v\n"; }

#
# Naive expectation (WRONG): Assignment should fail with 'attempt to access
# disallowed key' diagnostic.
#
# Observed behavior: Assignment succeeds, no diagnostic issued.
#
$h{five} = 5;

print "\nAfter assignment to \$h{five}:\n";
while (my ($k, $v) = each %h) { print "  $k => $v\n"; }

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About