Search code examples
perlhash

Looping through hashes in Perl gives odd result - example script provided


I'm revisiting a perl application that I built several years ago. I have to rebuild some of it. But today I'm stuck. I'm having some trouble with hashes. I have this test script that loops through some hashes. What I don't understand is that the second time the last loop gives 'pid1' => $VAR1->[1]{'deal'}{'pid1'} as output. I'm expecting a hash with product data. What am I doing wrong?

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

my %stores;

push @{$stores{'store1'}}, 'pid1';
push @{$stores{'store1'}}, 'pid2';
push @{$stores{'store2'}}, 'pid1';

print Dumper(\%stores);

my %products = (
  'pid1' => {
    'name'  => 'Product 1',
    'color' => 'red'
  },
    'pid2' => {
    'name'  => 'Product 2',
    'color' => 'blue'
  }
);

print Dumper \%products;

my @offers;
foreach my $storeid (keys %stores) {
  foreach my $pid (@{$stores{$storeid}}) {

    my %offer;

    $offer{$storeid}{'deal'}{$pid} = $products{$pid};
    push(@offers, %offer);
  }
}

print Dumper(\@offers);
$VAR1 = {
          'store1' => [
                        'pid1',
                        'pid2'
                      ],
          'store2' => [
                        'pid1'
                      ]
        };
$VAR1 = {
          'pid2' => {
                      'name' => 'Product 2',
                      'color' => 'blue'
                    },
          'pid1' => {
                      'color' => 'red',
                      'name' => 'Product 1'
                    }
        };
$VAR1 = [
          'store1',
          {
            'deal' => {
                        'pid1' => {
                                    'color' => 'red',
                                    'name' => 'Product 1'
                                  }
                      }
          },
          'store1',
          {
            'deal' => {
                        'pid2' => {
                                    'name' => 'Product 2',
                                    'color' => 'blue'
                                  }
                      }
          },
          'store2',
          {
            'deal' => {
                        'pid1' => $VAR1->[1]{'deal'}{'pid1'}
                      }
          }
        ];

Solution

  • It means

    $VAR1->[1]{'deal'}{'pid1'}   # $offers[1]{'deal'}{'pid1'}
    

    and

    $VAR1->[5]{'deal'}{'pid1'}   # $offers[5]{'deal'}{'pid1'}
    

    are both references to the same hash, which looks like

    {
      'color' => 'red',
      'name' => 'Product 1'
    }
    

    Maybe it's clearer if you use local $Data::Dumper::Purity = 1; to produce code that can actually be executed.

    $VAR1 = [
              'store1',
              {
                'deal' => {
                            'pid1' => {
                                        'color' => 'red',
                                        'name' => 'Product 1'
                                      }
                          }
              },
              'store1',
              {
                'deal' => {
                            'pid2' => {
                                        'name' => 'Product 2',
                                        'color' => 'blue'
                                      }
                          }
              },
              'store2',
              {
                'deal' => {
                            'pid1' => {}
                          }
              }
            ];
    $VAR1->[5]{'deal'}{'pid1'} = $VAR1->[1]{'deal'}{'pid1'};