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

Hello, I have a problem in passing a multidimensional array into a function. Below is a code representing the problem. The function "change" changes some values ($array[0][1]) in the input and returns the array, but the values in the original and even the backup array also changes (so I suppose it must be an issue with pointers). It doesn't happen when the array is singular (meaning replace $array[0][1] with $array[0]). All the values are changed to 5 but I want the original or at least backup not to change. Does it have to do with the fact that a multidimensional array is really an array of pointers?
use strict "vars"; main(); sub main { my @array; #original array $array[0][1]=1; #set one of its values my @array2=@array; #create a backup array my (@newarray) = change(@array); #feed it to a function print "new array value is".$newarray[0][1]."\n"; #print print "original array value is".$array[0][1]."\n"; print "array2 value is".$array2[0][1]."\n"; } sub change { my (@array)=@_; #take input $array[0][1]=5; #change value return (@array); #return }

Replies are listed 'Best First'.
Re: Problem in Passing A Multidimensional Array into a Function
by GrandFather (Saint) on Oct 02, 2008 at 02:06 UTC

    Perl doesn't talk about "pointers", it uses "references". It doesn't have multi-dimensional arrays, Perl has arrays of references (each of which may be to an array). Perl always passes parameters to subs by reference.

    If you want a temporary copy of a complicated data structure (that is really pretty much anything using references) you need to make a "deep copy". Perl doesn't have an inbuilt way to do that, but there are a number of modules that do the trick. Most common is Storable. Consider:

    use strict; use warnings; use Storable; use Data::Dump::Streamer; my $ref = [ {a => 1, b => 2, c => 3}, [1, 2, 3], {x => [4, 5, 6], y => [7, 8, 9]}, ]; my $org = Dump ($ref)->Out (); mangle ($ref); my $after = Dump ($ref)->Out (); print "Structure unmangled" if "$org" eq "$after"; sub mangle { my $cloned = Storable::dclone ($_[0]); $cloned->[0]{a} = 6; $cloned->[1][0] = 23; Dump $cloned; }

    Prints:

    $ARRAY1 = [ { a => 6, b => 2, c => 3 }, [ 23, 2, 3 ], { x => [ 4, 5, 6 ], y => [ 7, 8, 9 ] } ]; Structure unmangled

    Perl reduces RSI - it saves typing

      Here is an example of a deep copy, for reference. Note that this is not efficient - you'd be better off using a module as GrandFather suggests. (Modules are great for getting things done, but don't always show you how they are doing them.)

      my @a1; # First array # Pretend we're putting something in the first array. my @a2=aoacpy(@a1); sub aoacpy { my @array_in=@_; my @array_out; # Iterate through parent array. for (my $i=0; $i<scalar(@array_in); $i++) { # Iterate through child array - note that # we do this for each member of the parent # array. for (my $j=0; $j<scalar($array_in[$i]); $j++) { $array_out[$i][$j]=$array_in[$i][$j]; } } return @array_out; }

      I'm now scratching my head trying to work out why this is so slow - it shouldn't be iterating that many times.