in reply to Reference madness

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,

Replies are listed 'Best First'.
Re^2: Reference madness
by sdani (Novice) on Jul 31, 2017 at 12:58 UTC
    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.