in reply to Re: Keys() required to autovivify?
in thread Keys() required to autovivify?

Well, actually my code could just be replaced with perl -e ''. But this is just my demo code to show the problem that I encountered.

My real code looked like:

if (%{$h{x}}) { ... }
by which I meant to execute the body of the if statement only if $h{x} (was a hash and) had at least one element. But instead I got a syntax error. I had to switch to
if (keys %{$h{x}}) { ... }
which was more than I wanted to say.

I was wondering why the use of keys() made perl smart enough to autovivify my hash, but the use of %{$h{x}} wasn't enough to cause it to autovivify (and then return a false value since the autovivified hash value was empty).

Replies are listed 'Best First'.
Re^3: Keys() required to autovivify?
by shmem (Chancellor) on Dec 30, 2007 at 10:26 UTC
    only if $h{x} (was a hash and) had at least one element

    Then test whether the value of $h{x} actually is a hash reference.

    If you say keys %{$h{x}} it is assumed you know what you are doing and want autovivifying, while dereferencing an undef value could just be a mistake. strict 'refs' catches that - that is what strict is about ;-)

    By using keys you look inside the box (= the hashref), so perl autovivifies it, if it doesn't exist; by dereferencing you look at the box only.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Hmm. I'm not convinced. By using %{$h{x}}, I'm not saying anything different: i.e. I expect $h{x} to hold a hash, and I want it autovivified if $h{x} is undef. By using keys(%{$h{x}}), I'm saying: give me the list (or count) of keys in the hash in $h{x} and autovivify it if it's not there (returning an empty list or 0 from keys).
        i.e. I expect $h{x} to hold a hash

        That's the clue - you expect that, but it isn't. You look at the box, and you are dereferencing that undef value explicitly as a hash. If you access keys/values of an undef value, your dereference happens implicitly and the hashref is created (autovivification):

        use strict; my $f; $f->{foo} = 'bar'; # okay my ($h, %new); %new = %$h; # not okay

        Said otherwise, if you dereference something, you state that it is a reference, which is different to autovivication of an undef value into something.

        Clearer?

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}