Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does perl insert an undef value into my hash?

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


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.

>Solution :

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}).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading