You have this statement:
say for @{$x}
The value of $x
is undef, so when you dereference it, Perl notices that you want to use $x
as an array ref. It then creates the array for you ("autovivification"). That array is empty, so there's nothing that for
can iterate over.
Autovivification is the feature that enables us to do tasks like counting in this loop. When a key for $first
doesn't exist, Perl adds that key to the hash. But, there needs to be a second level hash where $second
can be a key. Since the value of the $first
key is undef, Perl autovivifies that second level hash so you can operate on it:
for ( ... ) {
# source.example.com dest.example.org 1234
my( $first, $second, $count ) = split;
$hash->{$first}{$second} += $count;
}
Image how hard this task would be if you had to know all the keys, hash sizes, and so on in advance, or had to extend or modify the data structure sizes yourself.
We have an extended example of this in Intermediate Perl, the book in the tutorial series where we talk about references. I also write about it in Understand autovivification.
@tobyink mentions the autovificiation pragma. It recognizes certain constructs and can warn or stop your program:
use v5.10;
use warnings;
no autovivification qw(store);
my $x;
for ( @$x ) {
say "Got value: $_";
}
say "End. x = $x";
Now the program stops:
Can't vivify reference at ...
But, all of this makes your program a bit slower as Perl has to do extra work to check all that.
There's also the StackOverflow answer How do I disable autovivification in Perl?, but I think the answers aren't that useful.
You should get used to autovivification and programming in an environment where it exists (along with all the other things that you can accidentally do to create bugs).