![]() |
How to copy an object created by fields::new
What is the best way to make a copy (not a deep copy) of an object
created by fields::new? My complete example program is below. +++++++++++++++++++++++++++++++++++++++++ #!/usr/local/bin/perl -wl use strict; package Ftest; use fields qw(foo bar xyzzy); sub new { my $class = shift; my __PACKAGE__ $self = fields::new($class); @$self{qw(foo bar xyzzy)} = @_; return $self; } package main; my Ftest $f = new Ftest 1,2,3; my Ftest $g = new Ftest; @$g = @$f; --------------------------------------------------------------------------------- The last line above does the actual copy. This version works with 5.8 as the fields implementation uses pseudo-hashes but it doesn't work with 5.9 because of course they are not array references. If I change it to... %$g = %$f .... then it works on both Perls but I get a warning about pseudo-hashes being deprecated on the 5.8 version. I am reluctant to include a no warnings 'deprecated'; statement. There is a good reason for this: One of the mistakes I frequently make, when declaring a scalar and assigning to it a reference to such an object, is to forget the type, i.e. my $foo = shift; instead of my Type $foo = shift; The warning about deprecated pseudio-hashes catches this which I find very useful. I particularly want my code to work with both 5.8 and 5.10 (when it arrives) and I don't want to put conditional code in there. |
Re: How to copy an object created by fields::new
Mintcake <tony@skelding.co.uk> wrote in comp.lang.perl.misc:
> What is the best way to make a copy (not a deep copy) of an object > created by fields::new? > > My complete example program is below. > > +++++++++++++++++++++++++++++++++++++++++ > #!/usr/local/bin/perl -wl > > use strict; > > package Ftest; > > use fields qw(foo bar xyzzy); > > sub new > { > my $class = shift; > my __PACKAGE__ $self = fields::new($class); I'd write that my __PACKAGE__ $self = $class->fields::new; so that fields::new is visibly called as a class method. > @$self{qw(foo bar xyzzy)} = @_; > return $self; > } > > package main; > > my Ftest $f = new Ftest 1,2,3; > my Ftest $g = new Ftest; > > @$g = @$f; > --------------------------------------------------------------------------------- > The last line above does the actual copy. This version works with 5.8 > as the fields implementation uses pseudo-hashes but it doesn't work > with 5.9 because of course they are not array references. If I change > it to... > > %$g = %$f > > ... then it works on both Perls but I get a warning about pseudo-hashes > being deprecated on the 5.8 version. I don't see the warning with neither 5.8.7 nor 5.9.4, but I'll pretend it's there. > I am reluctant to include a no warnings 'deprecated'; statement. There > is a good reason for this: One of the mistakes I frequently make, when > declaring a scalar and assigning to it a reference to such an object, > is to forget the type, i.e. > > my $foo = shift; > > instead of > > my Type $foo = shift; > > The warning about deprecated pseudio-hashes catches this which I find > very useful. Then isolate the copy process to a small scope and switch off the warning only there. Objects should be treated as opaque entities anyhow, so accessing them as arrays or hashes outside their class is a no-no. Instead, add a method ("clone", say) to class Ftest: sub clone { my $self = shift; my __PACKAGE__ $clone = ref( $self)->fields::new; no warnings 'deprecated'; %$clone = %$self; $clone; } Instead of saying %$g = %$f; use my $g = $f->clone; The "deprecated" warning won't appear with clone(), but will be active for the rest of your code. Anno -- If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers. |
Re: How to copy an object created by fields::new
Anno Siegel wrote: > Mintcake <tony@skelding.co.uk> wrote in comp.lang.perl.misc: > > What is the best way to make a copy (not a deep copy) of an object > > created by fields::new? > > > > My complete example program is below. > > > > +++++++++++++++++++++++++++++++++++++++++ > > #!/usr/local/bin/perl -wl > > > > use strict; > > > > package Ftest; > > > > use fields qw(foo bar xyzzy); > > > > sub new > > { > > my $class = shift; > > my __PACKAGE__ $self = fields::new($class); > > I'd write that > > my __PACKAGE__ $self = $class->fields::new; > > so that fields::new is visibly called as a class method. > I agree - much nicer > > @$self{qw(foo bar xyzzy)} = @_; > > return $self; > > } > > > > package main; > > > > my Ftest $f = new Ftest 1,2,3; > > my Ftest $g = new Ftest; > > > > @$g = @$f; > > --------------------------------------------------------------------------------- > > The last line above does the actual copy. This version works with 5.8 > > as the fields implementation uses pseudo-hashes but it doesn't work > > with 5.9 because of course they are not array references. If I change > > it to... > > > > %$g = %$f > > > > ... then it works on both Perls but I get a warning about pseudo-hashes > > being deprecated on the 5.8 version. > > I don't see the warning with neither 5.8.7 nor 5.9.4, but I'll pretend > it's there. It's there in 5.8.0 but not in 5.8.7. This suggests that the warning issued under these circumstances was deemed to be erroneous. There are a couple of other situations where this warning used to be issued but is no longer, e.g. keys %$g values %$g $g->{$key} > > > I am reluctant to include a no warnings 'deprecated'; statement. There > > is a good reason for this: One of the mistakes I frequently make, when > > declaring a scalar and assigning to it a reference to such an object, > > is to forget the type, i.e. > > > > my $foo = shift; > > > > instead of > > > > my Type $foo = shift; > > > > The warning about deprecated pseudio-hashes catches this which I find > > very useful. > > Then isolate the copy process to a small scope and switch off the warning > only there. Objects should be treated as opaque entities anyhow, so > accessing them as arrays or hashes outside their class is a no-no. > Instead, add a method ("clone", say) to class Ftest: > > sub clone { > my $self = shift; > my __PACKAGE__ $clone = ref( $self)->fields::new; > no warnings 'deprecated'; > %$clone = %$self; > $clone; > } > > Instead of saying > > %$g = %$f; > > use > > my $g = $f->clone; > > The "deprecated" warning won't appear with clone(), but will be active for > the rest of your code. I know I called them objects in the original post but they're not really. What I really wanted were restricted hashes with the added benefit of compile time key checking. I wanted to let users manipulate them as if they were hashes rather than hiding anything behind a method interface (other than the constructor of course) Incidentally, in your solution, the temporary lexical $clone is 'typed' but the $g scalar is not. It should be the other way around. There is no benefit in compile time key checking when no keys appear in the code. > > Anno > -- > If you want to post a followup via groups.google.com, don't use > the broken "Reply" link at the bottom of the article. Click on > "show options" at the top of the article, then click on the > "Reply" at the bottom of the article headers. |
| All times are GMT. The time now is 02:45 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.