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

I have used the method of passing arrays by reference to a subroutine so I can prevent them from being turned into one long array w/out problems...many times.
Now, however, I've come across the need to change the elements' values inside the subroutine, and I expected (because they are array refs) the values of those elements to be changed outside of the subroutine too. That is not happening though. Could somebody please point out my mistake.
Here is a sample script that illustrates my problem.
#!/usr/local/bin/perl ### Temp script to replicate oid_mod.pl ### use strict; my @a1 = qw(a b c); my @a2 = qw(d e f); foreach (@a2) { print "$_\n"; } changem(\@a1,\@a2); #pass-by-ref to allow extraction foreach (@a2) { print "$_\n"; } sub changem { my ($r1,$r2) = @_; my @arr1 = @{$r1}; my @arr2 = @{$r2}; print "BEFORE: $arr2[1]\n"; $arr2[1] = "q"; print "AFTER: $arr2[1]\n"; }
Expected Output:
d e f BEFORE: e AFTER: q d q f
Actual Output:
d e f BEFORE: e AFTER: q d e f
Why, when I print @a2 after the subroutine, has the value of $a2[1] not changed?
Thank you in advance.

Replies are listed 'Best First'.
Re: Array references inside a subroutine
by tcf22 (Priest) on Jul 16, 2003 at 19:59 UTC
    The lines
    my @arr1 = @{$r1}; my @arr2 = @{$r2};
    are derefencing the array references, and making copies of them. You are then in turn modifying the local copy of the array.
    Modifying it using
    $r2->[1] = "q";
    should do the trick.

    Update: $$r2[1] = "q"; will also work. It is your preference.
Re: Array references inside a subroutine
by thelenm (Vicar) on Jul 16, 2003 at 20:03 UTC

    Inside your subroutine, you are making copies of the referenced arrays (@arr1 and @arr2 are the copies), and then you are modifying the copies. If you want to change the original arrays, you should modify the references directly, something like this:

    sub changem { my ($r1,$r2) = @_; print "BEFORE: $r2->[1]\n"; $r2->[1] = 'q'; print "AFTER: $r2->[1]\n"; }

    -- Mike

    --
    just,my${.02}

Re: Array references inside a subroutine
by Anonymous Monk on Jul 16, 2003 at 20:11 UTC
    Thank you tcf22 and thelenm.
    That is why I've never had problems using the arrays' values (cuz a local copy is just fine). I just didn't think they were local copies this whole time. I thought I was just doing a simple type-cast.
    You both pointed my error out very clearly.
    Thanks Again :o)
Re: Array references inside a subroutine
by Mago (Parson) on Jul 17, 2003 at 01:23 UTC
    #!/usr/local/bin/perl ### Temp script to replicate oid_mod.pl ### use strict; my @a1 = qw(a b c); my @a2 = qw(d e f); foreach (@a2) { print "$_\n"; } @a2 = changem(\@a1,\@a2); #pass-by-ref to allow extraction foreach (@a2) { print "$_\n"; } sub changem { my ($r1,$r2) = @_; my @arr1 = @{$r1}; my @arr2 = @{$r2}; print "BEFORE: $arr2[1]\n"; $arr2[1] = "q"; print "AFTER: $arr2[1]\n"; return @arr2; }