Search code examples
perlpointershashreferencehashtable

Understanding Perl pointers to hashes in my script


So I know how the split is working, my question is how the pointer $p is working here. Does it have a different value for each iteration, and the value gets pushed on to the hash as an array? Is that how it will keep those values together when I need to extract them? I have over 100 lines of values I need to reference back to and I'm not sure how it will do that if $p is not changing with each iteration. Thanks!

else{
  my($site,$x,$y) = split /,/, $_; 
  my $p;
  $p->{site} = $site; 
  $p->{x} = $x; 
  $p->{y} = $y; 
  push @{$die_loc{$pattern}}, $p;
}

Solution

  • I take it that this is all in a loop where $_ is assigned every time through.

    You declare my $p every time so each gets its own memory location once it is assigned to. At that point it is autovivified into a hash reference, since that's how it is assigned. That reference is copied onto the array, so you will have them all. You can get the memory address of a reference using refaddr from the core module Scalar::Util. Or, for that matter, just print $p.

    What you have can be written as

    my $p = { site => $site, x => $x, y => $y };
    
    push @{$die_loc{$pattern}}}, $p;
    

    So after all is said and done, the hash %die_loc will under key $pattern have an array reference, which has for elements the hash references with keys site, x, and y.

    use feature 'say';
    
    foreach my $hr (@{$die_loc{$pattern}}) {
        say "site: $hr->{site}, x: $hr->{x}, y: $hr->{y}"
    }
    

    This prints a line for each (presumed) iteration that you processed. But generally you don't want to type key names but rather use keys to print a hash, for example

    foreach my $hr (@{$die_loc{$pattern}}) {
        say join ', ', map { "$_: $hr->{$_}" } sort keys %$hr;
    }
    

    where keys are also sorted for consistent prints. Or use a module, like Data::Dump.

    Note that references are a little different from pointers.

    There is only a code fragment posted so let me also say that you want to always start with

    use warnings 'all';
    use strict;