Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

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.


Comment on Problem Defining AoA from Named AoA
Select or Download Code
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 the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (23)
As of 2016-05-24 15:16 GMT
Find Nodes?
    Voting Booth?