tags:

views:

174

answers:

3

I have an array of various things including scalars and arrays. I want to make a copy of it, and tried the following:

@b = dclone(\@a)

but then when I try to read one of the scalar values from b, I get nothing back.

Everything appears to work when I copy it this way, though:

@b = @{dclone(\@a)}

What is the reason?

+14  A: 

dclone takes and returns references.

#! /usr/bin/perl

use Storable qw/ dclone /;

my @array = ( [1 .. 3], qw/ apple orange banana / );
my $copy = dclone \@array;

print ref($copy), "\n";

The output of the program above is ARRAY, so to get a deep-cloned array, use

my @copy = @{ dclone \@array };

To show what was going on without the dereference, the output of

my @copy = dclone \@array;

for (0 .. 4) {
  print "$_: ",
        (defined $copy[$_] ? $copy[$_] : "<undef>"),
        "\n";
}

is

0: ARRAY(0x1d396c8)
1: <undef>
2: <undef>
3: <undef>
4: <undef>

So assigning the result of dclone to an array will produce a single-element array, and trying to fetch any value other than the zero-th yields the undefined value.

Greg Bacon
+2  A: 

You need to dereference the return value of dclone which is a pointer (reference).

ennuikiller
+2  A: 

As said by a couple people dclone takes and returns references. That's good enough, but I think there is also the question of why?

As the documentation for Storable shows dclone( ... ) is the equivalent of composition of thaw and freeze as thaw( freeze( ... )). thaw can thaw any type of encoded structure. A reference can refer to anything in Perl. That array of hashes of arrays that you wanted, the hash of hashes of arrays, .... It relies upon you to know what you've asked for--and if not that at least for you to puzzle it out a little bit.

However, if you really dislike the syntax, and will be using the ARRAY -> ARRAY idiom enough to want to make it look better, you can write a wrapper function like so:

sub dclone_array (\@) { 
    use Storable 'dclone';
    my $in  = shift;
    my $out = dclone( $in );
    return @$out;
}

And use it like:

my @copy = dclone_array( @orig );
Axeman