How to correctly clone an object is a problem that people run into again and again and again, and the answer each time is that no general solution is possible.
Without semantic knowledge, it is not always possible to know in advance whether a shallow copy of the object is sufficient, whether a deep copy is required, or whether a correct copy requires something in between the two.
A shallow copy of an object treats instance data as static data that can be simply copied into a new instance. For some objects, including those based on arrays or hashes where all values are simple scalars, this works.
But as soon as a value is a reference to another object, you have to make a choice between simply copying the reference (i.e., making a shallow copy), or recursively cloning the referred-to object (i.e., making a deep copy). In a moderately sophisticated system, you're liable to run into objects that require some combination of shallow and deep copying in order to be successfully cloned.
| [reply] |
The problem here is that if your object contains references to other objects, the other objects get cloned too; if that is what you want, then Storable already provides dclone. You could copy only unblessed references by doing something like this:
sub sclone
{
while (defined(my $what = shift))
{
for my $r (ref $what)
{
($r eq 'ARRAY') && return
[map { sclone $_ } @$r];
($r eq 'HASH') && return do
{
my %s = map { $_ => sclone ($$r{$_}) } keys %$r};
\%s;
};
($r eq 'SCALAR') && return do
{
my $s = $$r; \$s;
};
return $r;
}
}
}
This can still cause problems, though... suppose you have a reference to a class variable? Now it points to an anonymous scalar, which isn't what you want. But suppose you have a reference to an anonymous scalar, and you just copy the reference directly? Now you have a pointer to the same anonymous scalar, which isn't what you want. There's no real way programatically to tell the difference, unless it's specified in the class somewhere... and if it is, then IMHO the class might as well have its own clone routine. | [reply] [d/l] [select] |
-13: my $copy_dump = Dumper $self;
-14:
-15: eval $copy_dump; warn $@ if $@;
+13: eval Dumper($self); warn $@ if $@;
Untested but that ought to work.
--
perl -p -e "s/(?:\w);([st])/'\$1/mg"
| [reply] [d/l] |
You can clone objects with CPAN module Storable.
use Storable (dclone);
...
my $obj2 = dclone($obj1);
It should be faster since Storable is XS (though I haven't done any benchmarks so I can be wrong).
Another option is CPAN module Clone. I've never tried it myself so I can't say anything about it. | [reply] [d/l] |