sdani has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, I need wisdom to find peace for my restless soul.... So, I'm trying to process a text file, slightly re-format it in a more usable format.
echo -e 'animal dog bark 2\nanimal dog woof 3\nanimal cat meaow 3' | p +erl -MData::Dumper -lane ' ($kind, $name, $say, $count) = @F; $h{$kind}{$name}{$say} = $count; END { foreach $kind (keys %h){ foreach $name (keys %{$h{$kind}}){ @say = keys %{$h{$kind}{$name}}; print Dumper \@say; $b{$name} = \@say; } } print Dumper %b }'
The output shows that when I print out the reference of the @say variable, that looks alright, but when I try to assign its value, somehow does not work. I'm sure, this problem is due to my bad knowledge of references, but it I could not find the solution elsewhere. Thanks for your guidance!

Replies are listed 'Best First'.
Re: Reference madness
by choroba (Cardinal) on Jul 31, 2017 at 12:06 UTC
    The problem is you are using global variables, in particular global @say. The assignment
    @say = keys %{$h{$kind}{$name}};
    changes the contents of the array, but \@say remains the same, i.e. what you assign to $b{$name} is still the same array.

    The common solution to the problem is to declare a new array for each iteration of the loop, i.e. use

    my @say = keys %{$h{$kind}{$name}};
    which will create a fresh new array with different \@say for each iteration of the loop;

    or create an anonymous array:

    $b{$name} = [ @say ];

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      Thank you very much for the answer, it fixed the problem. I would say it's a quite unexpected behaviour (at least by me), because when I dump \@say, it prints out the expected results (different for each animal), and when I initialised @say by @ say = () in the beginning of the loop, it gives also the bad results ("cat"=>"bark", "woof"). Thanks again! :D
        > I would say it's a quite unexpected behaviour (at least by me)

        Once you understand how references work, there's no surprise. \@say is the reference to @say, when you change the contents of @say, \@say still points to @say, i.e. to the new contents of it. When you store a reference, you don't store the contents.

        > when I dump \@say, it prints out the expected results (different for each animal)

        Of course. Otherwise, changing @say would have to edit the already printed output.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

        Hello sdani,

        I would say it's a quite unexpected behaviour..., because when I dump \@say, it prints out the expected results...

        That’s because Data::Dumper (like Data::Dump) applies a dereferencing operation to its argument if that argument is a reference. This is usually what you want; but to avoid it, just print the variable instead:

        23:27 >perl -MData::Dumper -wE "my @a = qw( a e i o u ); print Dumper( +\@a); print \@a;" $VAR1 = [ 'a', 'e', 'i', 'o', 'u' ]; ARRAY(0x4d2ec8) 23:27 >

        Note the square brackets in the output from Data::Dumper: they denote an anonymous array reference. See perlreftut.

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Think of the reference like the address of a room.

        You are changing the inhabitants of always the same (hotel) room and every time storing the address to this one room.

        Your dumps inside the loop only show the temporary inhabitants, but your last dump will only show the last inhabitants for always the same address.

        Using my will tell Perl to always create a new proper room with a unique address.

        Clearer?

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

        That should not be ... please give a code example illustrating that behavior.
Re: Reference madness
by LanX (Saint) on Jul 31, 2017 at 12:07 UTC
    > somehow does not work.

    Could you please be more explicit?

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!