http://qs1969.pair.com?node_id=11137191

dd-b has asked for the wisdom of the Perl Monks concerning the following question:

Hashes are defined to take string keys (though...stringification can make that work for random objects sometimes depending on what you expect of the value later; for just finding the object, and if the default stringification is unique among all such objects, it works).

I tried a weird thing, using lists as a hash key, and got remarkable results; Data::Dumper is claiming my hash has 3 members with the same key!

It was just playing around, and I don't see any important use for it (if I did, I'd need to understand it enough to really believe in it!; now I'm just a little curious).

This code:

use Data::Dumper; my %h1; $h1{(1, 1)} = 17; $h1{(2, 2)} = 19; $h1{('', 22)} = 23; $h1{(22, '')} = 22; my @h = (3, 4, 5); $h1{(@h)} = 44; print Dumper(\%h1);

Produces this output:

$VAR1 = { '22' => 22, '22' => 23, '11' => 17, '3' => 44, '22' => 19 };

(I observed this with perl 5, version 32, subversion 1 (v5.32.1) built for amd64-freebsd-thread-multi; I believe it's the default FreeBSD binary currently. So not an obscure environment.)

Replies are listed 'Best First'.
Re: Peculiar hash behavior
by jwkrahn (Abbot) on Oct 02, 2021 at 03:46 UTC

    Change:

    use Data::Dumper;

    To:

    use Data::Dumper; $Data::Dumper::Useqq = 1;
    $ perl -le' use Data::Dumper; $Data::Dumper::Useqq = 1; my %h1; $h1{(1, 1)} = 17; $h1{(2, 2)} = 19; $h1{("", 22)} = 23; $h1{(22, "")} = 22; my @h = (3, 4, 5); $h1{(@h)} = 44; print Dumper(\%h1); ' $VAR1 = { "2\0342" => 19, "1\0341" => 17, "\03422" => 23, "22\34" => 22, "3" => 44 };

    Or change the value of $;:

    $ perl -le' use Data::Dumper; my %h1; $; = "--"; $h1{(1, 1)} = 17; $h1{(2, 2)} = 19; $h1{("", 22)} = 23; $h1{(22, "")} = 22; my @h = (3, 4, 5); $h1{(@h)} = 44; print Dumper(\%h1); ' $VAR1 = { '2--2' => 19, '--22' => 23, '3' => 44, '1--1' => 17, '22--' => 22 };
Re: Peculiar hash behavior
by haukex (Archbishop) on Oct 02, 2021 at 06:59 UTC

      The array emulation is another one of those things I've read about a few times and never really understood well enough to be safe around :-) .

      I've been wondering if Data::Dumper is getting on towards its freshness date; I've played with alternatives a bit. Simpler (Data::Dump) does seem to be what's needed, and the ddx function is nicely adapted for debug use, as it says was intended. There do seem to be packages for the environments I care about (FreeBSD, Ubuntu, Raspberry Pi).

        I've been wondering if Data::Dumper is getting on towards its freshness date

        Data::Dumper has been maintained by P5P alongside the core, so it's unlikely to go stale. It's just a bit unfortunate (IMHO) that its Useqq option is off by default - the other options I use in the linked post are mostly for "nicer" output, so as long as you write use Data::Dumper; $Data::Dumper::Useqq=1;, the module is fine. Data::Dump has prettier output by default, but if you look at its issue list you'll see it's not perfect either. There are lots of other dumper modules out there. The main things to remember are that you want the modules to give unambiguous output (hence Useqq) and that these modules are debugging aids and not data serialization tools.

        > The array emulation is another one of those things I've read about a few times and never really understood well enough to be safe around :-) .

        I think it helps to know that Perl4 had no references˛, so none of the - now normal - nested data-structures described in perldsc were available.

        With the introduction of Perl5 multi-dim hashes had to be kept for backwards compatibility, but are for most an unknown or obscure feature.

        But they are quite handy sometimes, you'd be surprised how many people tend to reinvent something like $h{ join(",",@dims) }= "x" which is essentially the same without a safer separator.°

        HTH! :)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        °) a former boss was particularly proud to show me his "genius" trick to safe memory ...

        ˛) a lot had to be achieved with *type-globs (yuck)

        The array emulation is another one of those things I've read about a few times and never really understood well enough to be safe around :-) .

        $h{$x, $y, ...}
        is short for
        $h{join $;, $x, $y, ...}

        That's it.

        As long as your keys don't contain the value in $; (which is a control character by default), you can emulate multi-level hashes. It presumably uses less memory, but it might be a bit slower from concatenating the keys??? Of course, you're relying on the value of $; being safe.

Re: Peculiar hash behavior
by AnomalousMonk (Archbishop) on Oct 02, 2021 at 07:16 UTC

    For the $h1{(@h)} expression, note that an @array evaluated in scalar context yields the number of elements in the array. In the $h1{(@h)} expression, the @h array of three elements (used as a key/string) is evaluated in scalar context (update: so 3 → "3").


    Give a man a fish:  <%-{-{-{-<

      Yes, of course it does. Sigh.

      Bad luck for me that my test data started with '3', so it was easy to not realize that well-known thing was happening.