dol has asked for the wisdom of the Perl Monks concerning the following question:

Hello all!

Caveat: I'm fairly new to Perl so the answer may be obvious.

I'm trying to delete a key in a hash-of-hashes using references. I wrote some mock-up code isolating the issue:

#!/usr/bin/perl -w use strict; my %HoH = ( flintstones => { lead => "fred", pal => "barney", }, jetsons => { lead => "george", wife => "jane", "his boy" => "elroy", }, ); my $href1 = \%{$HoH{flintstones}}; my $href2 = $HoH{flintstones}; my $href3 = \%HoH; print "\$HoH{flintstones}: $HoH{flintstones}\n\$href1: $href1\n\$href2 +: $href2\n\$href3->{flintstones}: ",$href3->{flintstones},"\n"; #Works delete($HoH{flintstones}); #delete($href3->{flintstones}); #Fails #delete($href1); #delete($href2);

Output:

$ ./hashreftest2.pl $HoH{flintstones}: HASH(0x7ce220) $href1: HASH(0x7ce220) $href2: HASH(0x7ce220) $href3->{flintstones}: HASH(0x7ce220)

From the output all four variables look equivalent to me. But any of the last two commented delete lines (i.e. "delete($href1);" and "delete($href2);") fails with this error:

delete argument is not a HASH or ARRAY element or slice at ./hashreftest2.pl line 29.

I have searched the web but still can't understand why this happens. Any help is appreciated. In case it matters I'm running Perl v5.12.3 under Linux.

Thank you!

Replies are listed 'Best First'.
Re: Deleting from Hash-of-Hash using references
by JavaFan (Canon) on Nov 26, 2011 at 23:07 UTC
    Think of it this way, delete needs to pieces of information: the hash you delete from, and the key. $href1 is a reference to the *value* belonging to $HoH{flintstones}, while $href2 is the value itself.

    Given the reference, there's no way to find which key it belongs to. In fact, the value could appear several times in the hash, or even in different hashes.

      When you put it that way it makes sense. I thought I was referring to the key (which then in turn would point to the value and location), not the actual value in the hash.

      Thanks for the help.

Re: Deleting from Hash-of-Hash using references
by Marshall (Canon) on Nov 27, 2011 at 09:34 UTC
    Here is some code for you...
    I like pp in Data::Dump although it is not a core module, it is nice for compact representations of structures.

    In order to delete the keys associated with $href1 or $href2 (they are the same), it is necessary to cycle through the keys of %HoH, and compare $href1 against the values of those keys...

    #!/usr/bin/perl -w use strict; use Data::Dump qw(pp); use Data::Dumper; my %HoH = ( flintstones => { lead => "fred", pal => "barney", }, jetsons => { lead => "george", wife => "jane", "his boy" => "elroy", }, ); my $href1 = \%{$HoH{flintstones}}; my $href2 = $HoH{flintstones}; my $href3 = \%HoH; #Fails #yes, indeed this will fail!! #delete($href1); #delete($href2); # These are both references to the sub hash of flintstones... # sometimes the ability to omit parens in Perl is good thing # sometime not, here not: print pp ($href1), "\n"; #{ lead => "fred", pal => "barney" } print pp ($href2), "\n"; #{ lead => "fred", pal => "barney" } print "printing HOH...\n"; print pp ($href3), "\n"; #printing HOH... #{ # flintstones => { lead => "fred", pal => "barney" }, # jetsons => { "his boy" => "elroy", lead => "george", wife => "jane" + }, #} foreach my $TV_show (keys %HoH) { delete $HoH{$TV_show} if $HoH{$TV_show} == $href1; } print "printing HOH after the delete... flintstones are gone...\n"; print pp ($href3), "\n"; #printing HOH after the delete... flintstones are gone... #{ # jetsons => { "his boy" => "elroy", lead => "george", wife => "jane" + }, #}
    Update: it occurred to me, that perhaps you may want "flintstones" to point to an empty hash. in that case:
    change: delete $HoH{$TV_show} if $HoH{$TV_show} == $href1; to: $HoH{$TV_show}={} if $HoH{$TV_show} == $href1;
    $HoH{$TV_show}={} means: allocate new hash memory and assign a reference to it to $HoH{$TV_show}

      Thanks! Your code makes the distinction very clear.

      I ended up not using references in this case, there was really no need once I rewrote the mess that was my first draft. But it was an interesting lesson that I'm sure will be useful.