in reply to Why does testing a key create a hash?

This will eliminate autovivification:

my $hash = undef; print "shouldn't print\n" if $hash; # still prints nothing if( ref( $hash ) =~ /HASH/ and exists( $hash->{1} ) ) { print "Autovivified\n"; # Won't print; } print "Still shouldn't print.\n";

If you don't mind $hash suddenly becoming a hashref (despite being an empty hash), you can eliminate the $ref( $hash ) =~ /HASH/ portion of the check. Do see exists.

You're just getting bitten by autovivification. It's documented behavior.


Dave

Replies are listed 'Best First'.
Re^2: Testing a key creates a hash (ref--)
by tye (Sage) on Aug 17, 2005 at 23:39 UTC

    I don't like your ref-based test (it will give both false positives and false negatives). I'd just be sure to 'use strict' and do 'if $hash && $hash->{1}' instead. Perhaps 'if ref($hash) && $hash->{1}' would also be okay.

    Note that you can also use Data::Diver to avoid autovivification.

    I'd still really like to have a 'no autovivify' pragma... (:

    - tye        

      My point is that the following code will autovivifygenerate a hashref:

      use strict; use warnings; my $href; if( exists( $href->{1} ) ) { print "\$href->{1} = $href->{1}\n"; } print '$href is now a ', ref( $href ), " ref.\n";

      The output will be:

      $href is now a HASH ref.

      The point is that the existance test autoassigns a hash ref to $href in the case that $href was previously undefined.

      My example in my earlier post takes that into consideration, and takes care to not alter the contents of $href even if it was previously undef

      In practice I can't think of a time when I've cared whether a scalar holds an empty hashref or undef, but since we were on the topic of autovivification, I figured it would be advisable to give an example that didn't introduce another possibly confusing behavior.

      I am curious though, how ref will give false positives and negatives, if all it's being used for is to determine whether $href contains a hashref or not? That's exactly what ref does. If ref returns anything other than HASH there's no point proceeding to the exists test. If it returns nothing, once again there's no need to proceed to the exists test. But if it returns HASH, we can proceed to the exists test without worrying that $href will be altered from undef to HASH0xA1234F.

      If I'm missing something I'm open to listen.

      Your 'if ref($hash) && $hash->{1}' would return false negatives if $hash->{1} contains false or undef despite the key existing, and it would autovivify $hash->{1} if $hash contained a hashref, even if it didn't already exist, which doesn't prevent autovivification, I think. ;)

      In the case of if $hash && $hash->{1}, you could get the "Can't coerce xxxxx into hash at ...." messages if $hash contained anything besides the anticipated hash ref.


      Dave

        False negative: Bless your hash(ref). False positive: Bless you arrayref into "Tie::NotHASH".

        You appear to be confusing the return value of ref with the default stringification of a reference.

        But be aware that objects can override stringification and non-hash objects can override "hash dereference". This is why Data::Diver mostly uses eval to test for whether something can be used as a hash reference.

        - tye