Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Problem Defining AoA from Named AoA

by adeirossi (Initiate)
on Jan 13, 2007 at 10:21 UTC ( #594516=perlquestion: print w/replies, xml ) Need Help??
adeirossi has asked for the wisdom of the Perl Monks concerning the following question:

I'm a Perl beginner having trouble with arrays of arrays. When I define an AoA using a named AoA, both array names seem to refer to the same AoA. For example, if I first define @aoa1 with an anonymous AoA and then define @aoa2 with "my @aoa2 = @aoa1;", the modification of @aoa2 undesirably modifies @aoa1 (and vice versa).

The script below demonstrates this problem:
use strict; use warnings; my @aoa1 = ( # define @aoa1 w/ anonymous AoA ["-","-","-"], ["-","-","-"], ["-","-","-"], ); # my @aoa2 = ( # define @aoa2 w/ anonymous AoA # ["-","-","-"], # ["-","-","-"], # ["-","-","-"], # ); my @aoa2 = @aoa1; # define @aoa2 w/ named AoA # $aoa1[1][1] = '@'; # modify @aoa1 $aoa2[1][1] = '@'; # modify @aoa2 printAoa( "aoa1", @aoa1 ); # print @aoa1 printAoa( "aoa2", @aoa2 ); # print @aoa2 exit; sub printAoa { my ( $aoaName, @aoa ) = @_; my $row; my $col; print "*** $aoaName ***\n"; for $row ( 0 .. 2 ) { for $col ( 0 .. 2 ) { print "$aoa[$row][$col] "; } print "\n"; } print "\n"; }
I would expect the above script to print:
*** @aoa1 *** - - - - - - - - - *** @aoa2 *** - - - - @ - - - -
Instead, I get:
*** @aoa1 *** - - - - @ - - - - *** @aoa2 *** - - - - @ - - - -
It's as if @aoa1 and @aoa2 refer to the same AoA. When "$aoa2[1][1] = '@';" is commented out and "$aoa1[1][1] = '@';" is activated, the output is the same.

The only way I can get @aoa1 and @aoa2 to behave as I'd like is to define both of them with anonymous AoA's. If you comment out "my @aoa2 = @aoa1;" and uncomment the lines above it, the script produces the desired output. This is all well and good, but in my actual script, I need to define AoA's from named AoA's rather than anonymous ones.

Any suggestions would be greatly appreciated.


Replies are listed 'Best First'.
Re: Problem Defining AoA from Named AoA
by bsdz (Friar) on Jan 13, 2007 at 11:28 UTC
    I must admit this is not very intuitive. Although the wrapper list @aoa1 and @aoa2 point to different locations in memory the internal array references do not. This can be shown by doing something like this: -
    # these will be different # print \@aoa1."\n"; print \@aoa2."\n"; # but these won't be! # print $aoa1[0]."\n"; print $aoa2[0]."\n"; print $aoa1[1]."\n"; print $aoa2[1]."\n"; print $aoa1[2]."\n"; print $aoa2[2]."\n";
    You can get around this by using a deep clone, i.e.
    use strict; use warnings; use Storable qw(dclone); use Data::Dumper; # define @aoa1 w/ anonymous AoA # my @aoa1 = map { [qw(- - -)] } 0..2; # deep clone @aoa1 to create @aoa2 # my @aoa2 = @{dclone(\@aoa1)}; # modify @aoa2 # $aoa2[1][1] = '@'; # display structures # print Dumper(\@aoa1); print Dumper(\@aoa2);
    Perhaps this information should be added to the Array Tutorial.
Re: Problem Defining AoA from Named AoA
by bart (Canon) on Jan 13, 2007 at 12:01 UTC
    Both arrays are (different) flat arrays of items. They contain references — the same references. At least, references that point to the same thing. And if two variables hold a reference that points to the same thing, they're almost like aliases (different variables that act as if they're one and the same variable with a different name).*

    What you want to investigate is what they call a deep copy or deep cloning. I recall merlyn wrote a magazine article or two about them. See UR col 30.

    Also check out Storable, a standard module that includes a function for deep copying: dclone.

    p.s. The difference between variables containing the same reference, and aliases, is just this: only a direct full assignment to one of the variables, will break the interconnection. Let me give an example:

    $x = { a => 1 }; # a reference $y = $x; # a copy of a reference points to the same thing $y->{a}++; # increments $x->{a} $y->{b} = 3; # adds a hash item $x->{b} $y = { c => 0 }; # breaks the connection between $x and $y $y->{c}++; # no effect on $x
Re: Problem Defining AoA from Named AoA
by madbombX (Hermit) on Jan 13, 2007 at 16:45 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://594516]
Approved by bsdz
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2017-05-29 12:36 GMT
Find Nodes?
    Voting Booth?