Home > other >  Why does perl insert an undef value into my hash?
Why does perl insert an undef value into my hash?

Time:03-31

Let me start off with a simple minimal example:

use strict;
use warnings;
use Data::Dumper;

my %hash;
$hash{count} = 4;
$hash{elems}[$_] = {} for (1..$hash{count});

print Dumper \%hash;

Here is the result (reformatted):

$VAR1 = {
          'count' => 4,
          'elems' => [undef, {}, {}, {}, {}]
        };

I do not understand, why did the first element of $hash{elems} become an undef?


I know there are probably easier ways to do what I am doing, but I am creating these empty hashes so that I can later do my $e = $hash{elems}[$i] and continue to use $e to interact with the element, eg continue the horror of nested structures with $e->{subelems}[0] = 100.

CodePudding user response:

Array indices start at 0 in Perl (and in most programming languages for that matter).

In the 1st iteration of $hash{elems}[$_] = {} for (1..$hash{count});, $_ is 1, and you thus put {} at index 1 of $hash{elems}.

Since you didn't put anything at index 0 of $hash{elems}, it contains undef.

To remedy this, you could use push instead of assigning to specific indices:

push @{$hash{elems}}, {} for 1 .. $hash{count};

push adds items at the end of its first argument. Initially, $hash{elems} is empty, so the end is the 1st index (0).


Some tips:

  • The parenthesis are not needed in for (1..$hash{count}): for 1 .. $hash{count} works just as well and looks a bit lighter.

  • You could initialize your hash when you declare it:

     my %hash = (
         count => 4,
         elems => [ map { {} } 1 .. 4 ]
     );
    
  • Initializing elems with an arrayref of hashrefs is often useless, thanks to autovivification. Simply doing $hash{elems}[0]{some_key} = 42 will create an arrayref in $hash{elems}, a hashref at index 0 in this array, containing the key some_key with value 42.
    In some cases though, your initialization could make sense. For instance, if you want to pass $hash{elems} (but not $hash) to a function (same thing if you want to pass $hash{elems}[..] to a function without passing $hash{elems}).

  • Related