This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Deep Copying, aka, cloning around. =head1 VERSION Maintainer: Peter Scott <[EMAIL PROTECTED]> Date: 8 Aug 2000 Last-Modified: 29 Aug 2000 Mailing List: [EMAIL PROTECTED] Version: 3 Number: 67 Status: Frozen =head1 ABSTRACT Perl should have a C<clone> method for deep copying of hierarchical data structures. Damian Conway mooted a C<clone> function for deep copying of objects as part of an earlier discussion. This RFC expands upon that and gives it special attention. I expect several iterations of this RFC from feedback. =head1 DESCRIPTION The language interface is the C<clone> method which takes an object as argument and returns a copy of it as result: =over 4 =item clone SCALAR =item clone SCALAR, CALLBACK $copy = clone($obj) $copy = clone($obj, sub { die 'Filehandle copying not allowed' }) The C<CALLBACK> is an optional function to be called if C<clone> encounters a filehandle, dirhandle, or object with magic or an XS implementation. It will either throw an exception or return a value to be used as the cloned filehandle. =back =head1 IMPLEMENTATION =head2 Default The default functionality will switch on C<ref SCALAR> and recursively create new data structures in the way many people have written themselves. Here, for instance, is Garrett Goebel (C<[EMAIL PROTECTED]>)'s version implementing circular reference checking: our %SEEN = (); our $DEPTH = 0; sub clone { # Dereference and return a deep copy of whatever's passed our %SEEN; local $_ = ref($_[0]) or return $_[0]; exists $SEEN{$_} and return $SEEN{$_}; $DEPTH++; my $rval = /^HASH$/ ? {map {clone($_)} (%{$_[0]})} : /^ARRAY$/ ? [map {clone($_)} @{$_[0]} ] : /^SCALAR$/ ? \${$_[0]} : /^FORMAT$/ ? $_[0] # Shallow copy until we figure out : /^Regexp$/ ? $_[0] # B.pm and Class::Tom show the way : /^REF$/ ? $_[0] # how to deep copy these. Note: : /^IO$/ ? $_[0] # " : /^GLOB$/ ? $_[0] # " : /^CODE$/ ? $_[0] # " (B::Deparse) : $_[0]->CLONE; --$DEPTH and $SEEN{$_} = $rval or %SEEN = (); $rval; } =head2 Blessed objects If C<clone> encounters a blessed object C<$obj> say, it will call C<$obj->CLONE(CALLBACK)>. If the C<CLONE> method is not defined in C<$obj>'s class or any of its superclasses, C<UNIVERSAL::CLONE> will carry out the default functionality on the internal representation of C<$obj>. Probably this will mean little more than calling C<clone>. Classes (e.g., DBI) may well choose to throw an exception in their C<CLONE> methods. =head2 Filehandles If C<clone> encounters an C<IO::Handle>, its default behavior will be to make a copy of the filehandle (debatable: perhaps the default should be to throw an exception) unless a C<CALLBACK> function was specified, in which case it will use the return value of C<CALLBACK>. =head2 Tied variables If C<clone> encounters a tied variable, it will call the C<CLONE> method in the class of the underlying implementation object or fall back to C<UNIVERSAL::CLONE>. (Note: perhaps all missing functions from tied classes should punt to C<UNIVERSAL>. But that is outside the scope of this RFC.) =head2 Cyclic references The C<clone> function should detect circular references and replicate the same structure in the copy. One implementation that suggests itself is to keep a hash of input references with output references as values. It has been suggested that the code to do this will already be available in the garbage collector. =head2 Exceptions If an exception is thrown anywhere during the copying, it needs to be trapped so that C<clone> can clean up any cyclic references it has created, then rethrown. =head1 REFERENCES The L<Storable> module (http://search.cpan.org/doc/RAM/Storable-0.7.0/Storable.pm). The L<Data::Dumper> module (http://search.cpan.org/doc/GSAR/perl-5.6.0/ext/Data/Dumper/Dumper.pm).