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

I was a little surprised to find out:
use strict; my $self = {}; my $f1 = "aaa"; my $f2 = "bbb"; my $f3 = "ccc"; my $val = "val"; print "count = ".%$self."\n"; print "found\n" if exists $self->{$f1}{$f2}{$f3}; print "count = ".%$self."\n"; print "it is aaa\n" if exists $self->{$f1}; print "it is bbb\n" if exists $self->{$f1}{$f2}; print "it is ccc\n" if exists $self->{$f1}{$f2}{$f3}; print "count = ".%$self."\n";
That the exists key word is "creating" the hash...

Do I really need to test each one (left to right)?

Argh

Fixed code tags - dvergin 2002-07-03

Replies are listed 'Best First'.
Re: hash surprise
by DamnDirtyApe (Curate) on Jul 04, 2002 at 05:05 UTC

    Interesting. To quote the good Camel on exists:

    The function returns true if the specified hash key or array index exists in its hash or array. It doesn't matter whether the corresponding value is true or false, or whether the value is even defined.
    if (exists %hash{A}{B}{$key}) { ... }
    Although the last element will not spring into existence just because its existence was tested, intervening ones will. Thus $$hash{"A"} and $hash{"A"}->{"B"} will both spring into existence. This is not a function of exists, per se; it happens anywhere the arrow operator is used (explicitly or implicitly).

    Also, you want to wrap your code in <code>...</code> tags. That'll work fine.


    _______________
    D a m n D i r t y A p e
    Home Node | Email
      You left out the best part from the doc ;-)

      "This surprising autovivification in what does not at first--or even second--glance appear to be an lvalue context may be fixed in a future release." (empasis added)

      I think the hash key gets a value of "", can't see how that is good...

      Most of my hashes are balanced. By that I mean that I always fill all branches, but don't always define a leaf.

      So, this example seems to be a work around...at least for my purpose:

      use strict; my $self = {}; my $f1 = "aaa"; my $f2 = "bbb"; my $f3 = "CCC"; my $val = "val1"; # Create another valid branch $self->{$f1}{$f2}{DDD} = 'val2'; # Looking to test for: $self->{$f1}{$f2}{$f3} = val1 # But DON'T want to create anything if it isn't created print "pre count = ".%$self."\n"; print "found\n" if (defined $self->{$f1} && defined $self->{$f1}{$f2} + && defined $self->{$f1}{$f2}{$f3}); print "post count = ".%$self."\n";
Re: hash surprise
by Courage (Parson) on Jul 04, 2002 at 05:37 UTC
    Yes, this is mentioned autovivification feature.

    Usually this helps, but if you feel you need other behaviour, then it's easy to write a sub similar to "exists" without that feature:

    use strict; my %s; sub rexists (\%;@) { my ($href, @values) = @_; for (@values) { return 0 unless ref($href); return 0 unless exists $href->{$_}; $href = $href->{$_}; } return 1; } print rexists(%s,qw(a b c)),"\n"; $s{a}{b}{c} = 1; print rexists(%s,qw(a b c)),"\n";

    Courage, the Cowardly Dog.

Re: hash surprise
by Zaxo (Archbishop) on Jul 04, 2002 at 05:33 UTC

    Erm.. what do you expect? My naive inspection says ($self, $f1, $f2, $f3, $val) are completely independent.

    Do you mean for some of those symbols to be keys in $self? If you wish to define a method, it should be a sub in the namespace where the object is defined.

    If you really want to autovivify those keys, test for defined instead of exists.

    After Compline,
    Zaxo