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

I have a routine from Randal Schwartz's site at: http://www.stonehenge.com/merlyn/UnixReview/col30.html called deep copy which copies the contents of a reference to stuff in a deep manner rather than just copying the pointers.
My problem is it loses the object information if it's copying objects.
Any one have any idea of how to modify the routine to handle objects?
my $arrayObjsRef = \@arrayOfObjects; my $copy = _deep_copy( $arrayObjsRef ); sub _deep_copy { my $this = shift; my $ref = ref $this; if ( not ref $this ) { $this; } elsif ( ref $this eq "ARRAY" ) { [ map _deep_copy( $_ ), @$this ]; } else { # this is where the objects would be copied +{ map { $_ => _deep_copy( $this->{$_} ) } keys %$this }; } }

Replies are listed 'Best First'.
Re: deep_copy objects question
by GreyGlass (Sexton) on Aug 13, 2004 at 19:57 UTC
    Notice that Randal's code supports copying only structures composed of arrays and hashes. You really do not want to break object abstractions by copying their guts - it is bound to lead to problems sooner or later. Anyway, in the most general sense, you cannot always correctly copy objects, handles, code, etc.

    Code is a problem, since there may be persistent state associated with it - how do you duplicate it? Handles almost always have state that cannot be duplicated to an independent copy.

    Even if you assume that your structure does not contain anything but pure Perl objects, those object can contain references to code and handles. Moreover, the class implementations for the objects may be keeping class-wide state, which means the only valid way of copying the object implementation (from the class point of view) is to use a class-specific copy constructor, if the class allows this by implementing one.

    This, of course, does not disagree with the other posters' suggestions - you can always take the risk and just deep-copy and re-bless anything you find. Just watch out for the consequences.

      Thanks for the wisdom.
      I recoded to not require copying but hold onto the original references. But if I need to copy objects I'll use Clone or Storeable.
      Peace and a veritable lack of bugs.
      --jambo
Re: deep_copy objects question
by dragonchild (Archbishop) on Aug 13, 2004 at 19:24 UTC
    You need to bless the copy with the class the original was blessed into. You might want to take a look at Scalar::Util and the blessed() function, because not all objects are hashrefs (mine tend to be arrays) and, even if all your objects were hashrefs, then you'd assume all hashrefs were objects.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: deep_copy objects question
by Fletch (Bishop) on Aug 13, 2004 at 19:34 UTC

    There's also always Storable's dclone routine which handles blessed references as well.

Re: deep_copy objects question
by ihb (Deacon) on Aug 13, 2004 at 22:27 UTC

    One thing you really want to watch out for are recursive data structures.

    Try your clone code against

    my $foo = {}; $foo->{foo} = $foo;

    ihb

    Read argumentation in its context!

Re: deep_copy objects question
by johnnywang (Priest) on Aug 13, 2004 at 19:44 UTC
    In addition to Storable, there are some CPAN modules for cloning Clone