How to copy an object created by fields::new

Discussion in 'Perl Misc' started by Mintcake, Apr 12, 2006.

  1. Mintcake

    Mintcake Guest

    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.
    Mintcake, Apr 12, 2006
    #1
    1. Advertising

  2. Mintcake

    Anno Siegel Guest

    Mintcake <> 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.
    Anno Siegel, Apr 12, 2006
    #2
    1. Advertising

  3. Mintcake

    Mintcake Guest

    Anno Siegel wrote:
    > Mintcake <> 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.
    Mintcake, Apr 13, 2006
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jazz
    Replies:
    3
    Views:
    749
    Kristian Bisgaard Lassen
    Oct 28, 2003
  2. Alex
    Replies:
    2
    Views:
    1,203
  3. Replies:
    26
    Views:
    2,091
    Roland Pibinger
    Sep 1, 2006
  4. Cyril.Liu
    Replies:
    0
    Views:
    436
    Cyril.Liu
    Dec 2, 2008
  5. middletree

    how to copy from fields to other fields

    middletree, Nov 5, 2003, in forum: ASP General
    Replies:
    1
    Views:
    154
    middletree
    Nov 5, 2003
Loading...

Share This Page