in reply to Re: Generate Array of Hashes WITHOUT References
in thread Generate Array of Hashes WITHOUT References

Thanks for your reply, Rolf.

> Fascinating how most replyers misunderstood you're question, cause they read the title but not the code.

I didn't notice. Which posts are you refering to?

> This is wrong
> $rec=();
> You need to write %rec=() because you don't want references.

Sorry - typo on my part (that is what I meant to type). However, but after making that change in my code below:

#!/usr/bin/perl use Data::Dumper; use warnings; while ( <DATA> ) { #$rec = {}; #$rec = (); %rec = (); for $field ( split ) { ($key, $value) = split /=/, $field; $rec{$key} = $value; } push @AoH, \%rec; } print Dumper(\@AoH); __DATA__ A=1 B=2 C=3 Y=4 Z=5
...which includes the change of push'ing \%rec, I get this output:
$VAR1 = [ { 'Z' => '5', 'Y' => '4' }, $VAR1->[0] ];
Which is wrong, but if I change "%rec = ();" to "my %rec;" (as per Anonymous Monk's solution), I get what I want:
$VAR1 = [ { 'A' => '1', 'C' => '3', 'B' => '2' }, { 'Z' => '5', 'Y' => '4' } ];
Any ideas why? What's the significant difference between "%rec = ();" and "my %rec;" in this case?

> WHY don't you use warnings ??

No good reason (force of (bad) habit), but apart from the reason you mentioned in a later post, having tried "use warnings" in my code now (as above), it looks as if it would not have reported any problem. "use strict" may have helped.

Replies are listed 'Best First'.
Re^3: Generate Array of Hashes WITHOUT References
by parv (Parson) on Sep 10, 2014 at 14:34 UTC
    $VAR1 = [ { 'Z' => '5', 'Y' => '4' }, $VAR1->[0] ];

    The second element refers to the first element of the array reference. If $Data::Dumper::Deepcopy = 1;, then you will see that both array elements are the same.

    The problem is of variable scoping; see Coping with Scoping. I will try to explain but do wait for better|clearer explanation.

    Without my function, the hash %rec has scope file-wide (outside of the loop). The reference to the hash refers to that hash, the only copy. So modifying the only copy of the hash overwrites previous values (see by for { ... } print Dumper( \%rec ) ;). As the reference to the hash is saved twice, same values are repeated in Dumper() output.

    Use of my function inside the while loop limits the scope of %rec within the loop. On each iteration a *spanking new* hash is allocated, saving the values as references to each separate hash in the array as expected.

      Well explained, AF. Thanks for that!

      I tried $Data::Dumper::Deepcopy = 1;, and I see what you mean. One thing I don't understand is what you mean by:
        see by for { ... } print Dumper( \%rec ) ;
      I'd like to try that code, but what exactly should I type, coz the syntax doesn't look right yet?

        To start ...

        • ... means fill in the code as appropriate (and, author was too lazy to provide the whole thing not directly related to the point);
        • for { ... } is a reference to for loop code inside while loop;
        • then, print statement would go right after for loop.

        ... so  for { ... } print Dumper( \%rec ) ; expands to ...

        ... while ( <DATA> ) { ... for $field ( split ) { ... } print Dumper( \%rec ) ; push @AoH, \%rec; } ...