Problem with changes to referrenced object

Discussion in 'Perl Misc' started by rosenthd@yahoo.com, Nov 7, 2003.

  1. Guest

    Hi,

    I'd like to use a copy of my "test" object below without it being
    changed. However, all of my attempts so far to copy it don't seem
    to succeed. As the example shows below changing newarray affects the
    test object. How Can I copy values from the test array into a new
    array without changing the original test array.


    $test[0]{'A'} = 1;
    $test[1]{'A'} = 1;
    $test[2]{'A'} = 2;
    $test[2]{'C'} = 3;
    $test[3]{'B'} = 3;



    @newarray = @test;

    $testref = \@test;


    for ($x=0;$x<=$#{$testref};$x++)
    {
    #print "$x\n";
    foreach $elem (keys %{${$testref}[$x]})
    {
    print "$x: $elem, ${$testref}[$x]{$elem}\n";

    }

    }

    print "Setting G to 3\n";
    $newarray[0]{'G'}=3;


    for ($x=0;$x<=$#{$testref};$x++)
    {
    #print "$x\n";
    foreach $elem (keys %{${$testref}[$x]})
    {
    print "$x: $elem, ${$testref}[$x]{$elem}\n";

    }

    }

    Here's my output:

    0: A, 1
    1: A, 1
    2: A, 2
    2: C, 3
    3: B, 3

    Setting G to 3


    0: A, 1
    0: G, 3
    1: A, 1
    2: A, 2
    2: C, 3
    3: B, 3
     
    , Nov 7, 2003
    #1
    1. Advertising

  2. wrote:
    > I'd like to use a copy of my "test" object below without it being
    > changed. However, all of my attempts so far to copy it don't
    > seem to succeed. As the example shows below changing newarray
    > affects the test object. How Can I copy values from the test
    > array into a new array without changing the original test array.
    >
    > $test[0]{'A'} = 1;
    > $test[1]{'A'} = 1;
    > $test[2]{'A'} = 2;
    > $test[2]{'C'} = 3;
    > $test[3]{'B'} = 3;
    >
    > @newarray = @test;


    @test contains references to anonymous hashes, so @newarray is
    assigned references to just those anonymous hashes.

    Instead of

    @newarray = @test;

    you need to do something like

    for my $i (0..$#test) {
    for my $key ( keys %{ $test[$i] } ) {
    $newarray[$i]{$key} = $test[$i]->{$key};
    }
    }

    @newarray now contains references to _copies_ of the anonymous hashes
    instead of references to the original ditto.

    HTH

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Nov 7, 2003
    #2
    1. Advertising

  3. [posted & mailed]

    On Fri, 7 Nov 2003 wrote:

    >I'd like to use a copy of my "test" object below without it being
    >changed. However, all of my attempts so far to copy it don't seem
    >to succeed. As the example shows below changing newarray affects the
    >test object. How Can I copy values from the test array into a new
    >array without changing the original test array.


    You want to make a "deep copy", not a "shallow copy". A shallow copy only
    goes one level deep, whereas a deep copy is thorough, and copies EACH
    level of reference.

    You might want to use the Storable module's dclone() function.

    Also, I suggest reading

    http://www.stonehenge.com/merlyn/UnixReview/col30.html

    --
    Jeff Pinyan RPI Acacia Brother #734 2003 Rush Chairman
    "And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)
     
    Jeff 'japhy' Pinyan, Nov 7, 2003
    #3
  4. Eric Bohlman Guest

    wrote in
    news::

    > I'd like to use a copy of my "test" object below without it being
    > changed. However, all of my attempts so far to copy it don't seem
    > to succeed. As the example shows below changing newarray affects the
    > test object. How Can I copy values from the test array into a new
    > array without changing the original test array.
    >
    >
    > $test[0]{'A'} = 1;
    > $test[1]{'A'} = 1;
    > $test[2]{'A'} = 2;
    > $test[2]{'C'} = 3;
    > $test[3]{'B'} = 3;
    >
    >
    >
    > @newarray = @test;


    @newarray will be what's known in the business as a "shallow copy" of
    @test, which means that the actual array elements will be copied, but the
    things they reference won't. In other words, you'll have two arrays of
    references to the *same* hashes, giving you the result you experienced.

    What you need is a "deep copy" or "clone" of @test. Probably the easiest
    way to do it is to get the Clone::Any module from CPAN, which will provide
    you with functions that make cloning nested data structures simple.
     
    Eric Bohlman, Nov 8, 2003
    #4
    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. T-Boy

    detect changes in an object

    T-Boy, Apr 6, 2004, in forum: Java
    Replies:
    2
    Views:
    610
    Tim Slattery
    Apr 6, 2004
  2. John
    Replies:
    4
    Views:
    1,521
  3. Yasutaka Ito
    Replies:
    1
    Views:
    118
    Norman Yuan
    Jan 27, 2004
  4. mmac
    Replies:
    4
    Views:
    129
  5. Max Muermann

    Observing changes in object state

    Max Muermann, Aug 24, 2006, in forum: Ruby
    Replies:
    4
    Views:
    120
    Max Muermann
    Aug 25, 2006
Loading...

Share This Page