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

A co-worker just sent me a snippet of code and asked why it behaved like it does, and I can't really figure out why it does, can someone explain this behavior to me?
perl -w -e 'use strict;my $t; if (scalar (keys %{$t->{r}})) {print "There are keys\n";} print "t->{r} = $t->{r}\n"; ' t->{r} = HASH(0x80fbc50)
If I omit the if and only does:
perl -w -e 'use strict;my $t = undef; my %p = %{$t->{r}}; print "t->{r} = $t->{r} "; '
I get this error:
Can't use an undefined value as a HASH reference at -e line 2.
Why is it behaving like this? I can't see why $t->{r} gets defined in the first snippet

Replies are listed 'Best First'.
Re: does if(%{$ptr->{key}}) define?
by robartes (Priest) on Oct 03, 2002 at 09:08 UTC
    Hi jmo,

    I bet you never would have predicted this when you got up this morning, but you are witnessing a process called autovivification. Basically, when you dereference an undefined value in a context that sssumes it exists, it gets created automatically. In your case:

    keys %{$t->{r}}

    is the place where the autovivification occurs. You are dereferencing $t as if it were a hashref, so it gets created as a hashref. The same thing happens to $t->{r}, because that gets dereferenced by the keys %{ } construct.

    Now, my understanding of autovivification is imperfect, so I might be wrong on the subtleties (or even the big picture) here. Somebody else will pipe in if I am.

    You can get more information on autovivification in perlref.

    CU
    Robartes-

Re: does if(%{$ptr->{key}}) define?
by Juerd (Abbot) on Oct 03, 2002 at 08:23 UTC

    I think this answers your question.

    perl -w -e 'use strict;my $t = undef; my %p = keys %{$t->{r}}; print "t->{r} = $t->{r} "; '

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.