RE: RFC 67 (v1) Deep Copying, aka, cloning around.
From: Peter Scott [mailto:[EMAIL PROTECTED]] I would like deep copying to include copying CODE. It would be useful for implementing object methods... Why would it be necessary to deep copy a CODE reference? It might not be necessary. I'm still learning how to write kosher Perl... elegance is a long way off for me. It'd be nice to for a class to be able to initialize a new object containing a copy of an anonymous subroutine instead of a reference to a common one. There might be some real justification when used with closures. Then class methods could pass through to object methods that could be switched at runtime. Besides, it wouldn't be deep copying if it shallow copied the subroutines ;) If deep copying and cloning are though of in terms of persistent objects... aka Data::Dumper and Storable, then deparsing subroutines into something that can be stored becomes more important too. Class::Tom does this pretty well. Garrett
RE: RFC 67 (v1) Deep Copying, aka, cloning around.
Here's a version of my own kludgey deep copy. -Updated to use our mythical -CLONE method, and watch for circular references... our %SEEN = (); our $DEPTH = 0; %a = (a = 1, b = 2, c = [{a = 1, b = [1,2,3]}, 1, 2, 3]); *b = dcopy(\%a); sub dcopy { # 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 {dcopy($_)} (%{$_[0]})} : /^ARRAY$/ ? [map {dcopy($_)} @{$_[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{$_} = ref($rval) or $SEEN = (); $rval; } (/^$/ || /^CODE$/) return $obj; /^SCALAR|REF$/ return \clone $$obj; /^ARRAY$/ return [ map clone($_), @$obj ]; /^HASH$/ return { map {$_, clone $obj-{$_}} keys %$obj }; TODO: behavior for CGLOB, CREGEX, and CLVALUE. I would like deep copying to include copying CODE. It would be useful for implementing object methods... =head2 Filehandles If Cclone encounters an CIO::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 CCALLBACK function was specified Doesn't this fall under $obj-CLONE? Speaking of UNIVERSAL::CLONE is it really more complicated than a special case of the above dcopy subroutine? Hmm... I guess I'm not covering tied variables... our %SEEN = (); our $DEPTH = 0; sub CLONE { # Dereference and return a deep copy of whatever's passed our %SEEN; my $ref = ref($_[0]) or return $_[0]; exists $SEEN{$_} and return $SEEN{$_}; $DEPTH++; my ($a,$z) = (qr/(^|^.*?=)/, qr/\(.*?\)$/); my $r = ($_[0] =~ /${a}HASH$z/) ? {map {dcopy($_)} (%{$_[1]})} : ($_[0] =~ /${a}ARRAY$z/) ? [map {dcopy($_)} @{$_[1]} ] : ($_[0] =~ /${a}SCALAR$z/) ? \${$_[1]} : ($_[0] =~ /${a}FORMAT$z/) ? $_[0] : ($_[0] =~ /${a}CODE$z/) ? $_[0] : ($_[0] =~ /${a}Regexp$z/) ? $_[0] : ($_[0] =~ /${a}REF$z/)? $_[0] : ($_[0] =~ /${a}IO$z/) ? $_[0] : ($_[0] =~ /${a}GLOB$z/) ? $_[0] : croak "unknown data type $_[0] $ref"; --$DEPTH and $SEEN{$_} = ref($rval) or $SEEN = (); $ref !~ /^(HASH|ARRAY|SCALAR|GLOB|FORMAT|CODE|Regexp|REF|IO)$/ and bless $r, $ref or $r; }
Re: RFC 67 (v1) Deep Copying, aka, cloning around.
"GG" == Garrett Goebel [EMAIL PROTECTED] writes: GG Oops, my circular ref code is/was screwy... and $SEEN{$_} = $rval or $SEEN = (); that last line looks screwy too! :-) assigning an empty list to a scalar? i think you meant to assign to %SEEN. but why reinvent the wheel with this code? we have modules which do close to this now, and we have talked about using the GC traverse engine as well. uri -- Uri Guttman - [EMAIL PROTECTED] -- http://www.sysarch.com SYStems ARCHitecture, Software Engineering, Perl, Internet, UNIX Consulting The Perl Books Page --- http://www.sysarch.com/cgi-bin/perl_books The Best Search Engine on the Net -- http://www.northernlight.com
RE: RFC 67 (v1) Deep Copying, aka, cloning around.
At 04:17 PM 8/8/00 -0500, Garrett Goebel wrote: Here's a version of my own kludgey deep copy. -Updated to use our mythical -CLONE method, and watch for circular references... Great stuff, I've put it in v2. [snip] : /^CODE$/ ? $_[0]# " (B::Deparse) [snip] I would like deep copying to include copying CODE. It would be useful for implementing object methods... Why would it be necessary to deep copy a CODE reference? =head2 Filehandles If Cclone encounters an CIO::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 CCALLBACK function was specified Doesn't this fall under $obj-CLONE? IO::Handle appears to be what the builtin filehandles are these days (I'm trying to keep up; IO::Handle is mentioned in Camel III under ref(), but 5.6.0 filehandles still say GLOB - hmm, mebbe IO::Handle is just for sockets...). Either way, yes, CLONE would or could be a method of the IO::Handle class but I wanted to make it explicit. Speaking of UNIVERSAL::CLONE is it really more complicated than a special case of the above dcopy subroutine? Nope, it would indeed call that subroutine and not much else. But I think dcopy/clone will end up being an internal, not Perl code. -- Peter Scott Pacific Systems Design Technologies
Re: RFC 67 (v1) Deep Copying, aka, cloning around.
=head1 TITLE Deep Copying, aka, cloning around. The CCALLBACK is an optional function to be called if Cclone encounters a filehandle. ...or anything else it doesn't know how to handle. If Cclone encounters a tied variable, it will call the CCLONE method... ...of the underlying implementation object... or fall back to CUNIVERSAL::CLONE. =head1 REFERENCES The Storable and Data::Dumper modules
Re: RFC 67 (v1) Deep Copying, aka, cloning around.
wacko idea: combine a generic data tree traverse engine with damian's switch op. you pass this new smart traverse a ref and it will scan the tree. at every node it sees, it can call callbacks or methods. it can do the callbacks in pre, in or post ordering to get useful effects. if a node is an object, the optional method can be called (e.g. CLONE). each node could also be handled by a switch on its type. so this traverse engine could be shared by GC, clone, Data::Dumper, Storable, etc. just musing, uri -- Uri Guttman - [EMAIL PROTECTED] -- http://www.sysarch.com SYStems ARCHitecture, Software Engineering, Perl, Internet, UNIX Consulting The Perl Books Page --- http://www.sysarch.com/cgi-bin/perl_books The Best Search Engine on the Net -- http://www.northernlight.com
Re: RFC 67 (v1) Deep Copying, aka, cloning around.
At 06:10 PM 8/8/00 -0400, Uri Guttman wrote: wacko idea: combine a generic data tree traverse engine with damian's switch op. you pass this new smart traverse a ref and it will scan the tree. at every node it sees, it can call callbacks or methods. it can do the callbacks in pre, in or post ordering to get useful effects. if a node is an object, the optional method can be called (e.g. CLONE). each node could also be handled by a switch on its type. so this traverse engine could be shared by GC, clone, Data::Dumper, Storable, etc. I like it. Can you tell me what semantics you use with something like this to get behavior like clone's, where the reult of a node depends on the results of other nodes? Whether they've been visited already or not, how do you parcel all the results of, say, a ref-to-array together? -- Peter Scott Pacific Systems Design Technologies