in reply to Generate Array of Hashes WITHOUT References

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

This is wrong

$rec=();

You need to write %rec=() because you don't want references.

WHY don't you use warnings ??

Cheers Rolf

(addicted to the Perl Programming Language and ☆☆☆☆ :)

Replies are listed 'Best First'.
Re^2: Generate Array of Hashes WITHOUT References
by dsheroh (Monsignor) on Sep 09, 2014 at 11:48 UTC
    Fascinating how most replyers misunderstood you're question, cause they read the title but not the code.
    I fail to see how explanations that you can only store scalars (such as references, but not hashes) in an array imply a misunderstanding of the questions asked in the OP, which, for reference, are: "I'd like to know how to do that without using references?" and "How can I do the same code the same thing without using references?"

    You need to write %rec=() because you don't want references.
    ...and that still won't work, because the code ultimately does a push @AoH, $rec; Changing $rec to %rec will just plain not work because, even without strict, $rec and %rec are two different variables with no direct connection between them, so it would just be pushing an undef into @AoH.

    Of course, that could easily be fixed by changing the push to push @AoH, %rec;, which will work... but it will do something completely different than what the OP wants, as explained in b4swine's answer.

    Guess you misunderstood the question because you started reading the code, then addressed the first problem you saw without bothering to read all the code.

    The answer to the question actually asked, as previous posters have correctly understood, is "You can't do that without using references."

      > I fail to see how explanations that you can only store scalars ..

      I read the question as:

      "How can I avoid the dereferencing in $rec->{$key}=$value " and not "How can I store non-ref hashes in arrays."

      He tried $rec{$key}=$value but failed b/c he used %rec now.

      > ...and that still won't work, because the code ultimately does a push @AoH, $rec;

      true, but this was already demonstrated by Hameed but w/o explanation ... an explanation I added, without testing the code.

      Telling the OP (like most did here) that he can ultimately only store refs doesn't answer his question how to avoid dereferencing BEFORE storing.

      Of course most of his errors would have easily be visible if he used strict and warnings .

      But - alas - he mentioned that he took the code from the perldocs which (like I checked) don't use these pragmas either. :-(

      Finally I posted from mobile, it's hard to give working code from Android.

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re^2: Generate Array of Hashes WITHOUT References
by Anonymous Monk on Sep 09, 2014 at 08:27 UTC
    That is only half a third of it LanX :)
    #!/usr/bin/perl -- # reading from file # format: LEAD=fred FRIEND=barney # # # #!/usr/bin/perl -- use strict; use warnings; use Data::Dump qw/ dd /; my @AoH; while ( <> ) { my %rec; for my $field ( split ) { my( $key, $value ) = split /=/, $field; $rec{$key} = $value; ## second half } push @AoH, \%rec; } dd( \@AoH ); __END__
      Hameed already posted this.

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

        Hi LanX,

        > Hameed already posted this.

        Sort of, but he redesigned the code so much that it no longer created more than element in the array. See how there is only 1 loop. Part of the problem with this is, it doesn't demonstrate how %rec should be reinitialised at the start of each iteration of the outer loop (though I now know this).

      Good answer, Anonymous Monk.
      Thank you!
Re^2: Generate Array of Hashes WITHOUT References
by tel2 (Pilgrim) on Sep 10, 2014 at 01:14 UTC
    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.

      $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?