Home > Software engineering >  Perl :: Can You Have a Lists of Objects Within a Hash?
Perl :: Can You Have a Lists of Objects Within a Hash?

Time:11-23

In Perl (v5.30.0), I have a script that puts some scalars and then a list of objects into a "container" hash. The list of objects seems to be problematic, but I'm uncertain what I'm doing wrong.

Here's my code:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

package Person;
sub new
{
        my $type = shift;
        my %params = @_;
        my $self = {};
        $self->{'firstName'} = $params{'firstName'};
        $self->{'lastName'} = $params{'lastName'};
        bless $self, $type;
}

package main;

# I make a string:
my $string = "Some metadata...";

# I make a list of objects:
my @PersonArr = ();
push @PersonArr, Person->new( 'firstName' => "John", 'lastName' => "Schmitt" );
push @PersonArr, Person->new( 'firstName' => "Alice", 'lastName' => "Schwear" );

# I put the above into a hash:
my %outerHash = ( 'string' => $string,                  # LINE 28
        'PersonArr' => @PersonArr
);

print Dumper(\%outerHash);

Output is:

Odd number of elements in hash assignment at ./HashTest.perl line 28.
$VAR1 = {
          'Person=HASH(0x5559c89e8008)' => undef,
          'string' => 'Some metadata...',
          'PersonArr' => bless( {
                                  'firstName' => 'John',
                                  'lastName' => 'Schmitt'
                                }, 'Person' )
        };

Hmm. So the scalar string is intact, but I'm surprised that my list of Person objects seems to be disheveled. Poor Alice Schwear seems to have been "hashed" as undef somehow. There's also that strange Odd number of elements in hash assignment message; I have two entries in the hash, and two Person objects in array @PersonArr. Two hash entries should be an even number of elements, right...?

Just for giggles, I added a third person, making the code this:

push @PersonArr, Person->new( 'firstName' => "John", 'lastName' => "Schmitt" );
push @PersonArr, Person->new( 'firstName' => "Alice", 'lastName' => "Schwear" );
push @PersonArr, Person->new( 'firstName' => "Ruby", 'lastName' => "Baker" );  # NEW!

Now my output is this:

$VAR1 = {
          'PersonArr' => bless( {
                                  'firstName' => 'John',
                                  'lastName' => 'Schmitt'
                                }, 'Person' ),
          'Person=HASH(0x56350cc57008)' => bless( {
                                                    'lastName' => 'Baker',
                                                    'firstName' => 'Ruby'
                                                  }, 'Person' ),
          'string' => 'Some metadata...'
        };

More and more curious. There's no Odd number of elements in hash assignment error this time. And while John (Person #1) and Ruby (Person #3) are visible, Alice (Person #2) is completely gone from the picture.

What could be going on here? I'd love to understand what is happening. And more importantly, I'd love to fix this syntax, if it is fixable. Thank you.

CodePudding user response:

  • => is just a fancy , that autoquotes the left-hand side.
  • An array in list context produces the values of the array.

So,

my %outerHash = (
   'string' => $string,
   'PersonArr' => @PersonArr
);

means

my %outerHash = ( 'string', $string, 'PersonArr', $PersonArr[0], $PersonArr[1] );

And if we write that fancily, we get

my %outerHash = (
   string        => $string,
   PersonArr     => $PersonArr[0],
   $PersonArr[1] =>
);

Hash values can only be scalars. But references are scalars, so the hash values can be references to arrays.

my %outerHash = (
   string    => $string,
   PersonArr => \@PersonArr,
);
  • Related