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

Pardon my ignorance, but why does Perl do this:
my @a = ( {}, {}, {} ); print $a[3]{foo}; print scalar @a . "\n";
This prints the number 4, although @a should only have 3 elements. It seems that $a[3] is created on the fly while reading it. I would of course understand this if I assigned a value to $a[3]{foo}, but here I am only reading - which should be non-destructive (or non-constructive, for that matter). I humbly beg for enlightenment...

Replies are listed 'Best First'.
Re: Strange behaviour reading from hashref stored in array
by moritz (Cardinal) on Feb 16, 2009 at 15:00 UTC
    This behaviour is called "autovivification", and is a feature, not a bug of Perl. The background is that you treat $a[3] as a reference, and then perl thinks "if it should be a reference, let's make it one" and humbly turns an undef into a hash reference.

    If you don't want autovivification to happen, you can use modules such as Data::Diver to access elements of nested data structures.

    Since this behaviour confuses some people, Perl 6 autovivifies only if in lvalue context (ie if stuff is being assigned to it).

Re: Strange behaviour reading from hashref stored in array
by Random_Walk (Prior) on Feb 16, 2009 at 15:36 UTC

    As moritz says this is auto vivification. There is a way you can test if a key exists without the side effect of creating it

    my @a = ( {}, {}, {} ); print $a[3]{foo} if exists $a[3] and exists $a[3]{foo}; # or if you only want to ensure you don't expand @a # print $a[3]{foo} if exists $a[3]; print scalar @a . "\n";

    not the most attractive looking code though

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
Re: Strange behaviour reading from hashref stored in array
by Narveson (Chaplain) on Feb 16, 2009 at 15:01 UTC

    You won't create $a[3] if you just

    print $a[3];