$foo = {dates => [7,14,21],
times => [2,5,8]};
$bar = $foo;
$bar->{dates}->[0] = 2;
now:
print $foo->{dates}->[0];
2
The DeepCopy.pm package (inspired by an article I read but can't find
now in SysAdmin magazine, I think by Randal Schwartz) implements a
generic deep copier. It (tries to) create a 'fresh' copy of $foo, with
all references pointing to new data, not the same points as the old
reference. I'm posting it here and welcome any comments, critiques,
even flames. It's also on my tips page,
http://demog.berkeley.edu/~aperrin/tips . It runs fine under -w and
use strict.
Usage:
use DeepCopy;
$bar = copy $foo;
The module:
package DeepCopy;
require Exporter;
@ISA=qw/Exporter/;
@EXPORT=qw/copy/;
sub copy {
# copy $_[0] and return a freshly-reffed version.
my ($out,$bless);
my $orig = shift;
my $type = ref $orig;
return $orig unless $type;
unless ($type =~ /SCALAR|REF|CODE|ARRAY|HASH|GLOB/) {
$bless = $type;
if (UNIVERSAL::isa($orig,'SCALAR')) {
$type = 'SCALAR';
} elsif (UNIVERSAL::isa($orig,'REF')) {
$type = 'REF';
} elsif (UNIVERSAL::isa($orig,'CODE')) {
$type = 'CODE';
} elsif (UNIVERSAL::isa($orig,'ARRAY')) {
$type = 'ARRAY';
} elsif (UNIVERSAL::isa($orig,'HASH')) {
$type = 'HASH';
} elsif (UNIVERSAL::isa($orig,'GLOB')) {
$type = 'GLOB';
} else {
warn 'I am now deeply lost.';
return $orig;
}
}
if ($type eq 'SCALAR' or
$type eq 'REF' or
$type eq 'CODE') {
my $foo = $orig;
$out = \$foo;
} elsif ($type eq 'ARRAY') {
push @$out, copy($_) for @$orig;
} elsif ($type eq 'HASH') {
$out->{$_} = copy($orig->{$_}) for keys %$orig;
} elsif ($type eq 'GLOB') {
warn 'GLOB copy unimplemented';
my $foo = $orig;
$out = \$foo;
} else {
warn 'I am now deeply lost.';
}
bless $out, $bless if $bless;
return $out;
}
1;
--
---------------------------------------------------------------------
Andrew J. Perrin - ape...@demog.berkeley.edu - NT/Unix Admin/Support
Department of Demography - University of California at Berkeley
2232 Piedmont Avenue #2120 - Berkeley, California, 94720-2120 USA
http://demog.berkeley.edu/~aperrin --------------------------SEIU1199
You could lookup up a global hash that would contain extra copy
methods. Modules like Set::Object (which stores elements outside
script space) could register themselves with DeepCopy. The result
would be an extensible system.
--
V
VLR Jean-Louis Leroy
F http://users.skynet.be/jll
Use serialization/deserialization instead. See the docs of any
serialization module (FreezeThaw/Storable etc).
> use DeepCopy;
>
> $bar = copy $foo;
$foo = \$foo;
$bar = copy $foo;
Believe me, you do *not* want to reinvent *this* particular bicycle.
Ilya