edo has asked for the wisdom of the Perl Monks concerning the following question:

use strict; sub fiddleHash($) { my ($ref_hash) = @_; delete $ref_hash->{Quantity}{x}; } sub displayHash($) { my ($ref_Hash) = @_; foreach (keys %{$ref_Hash->{Quantity}}) { print "$_:$ref_Hash->{Quantity}{$_}\n"; } } my %hash1 = ( Quantity => { x => 1, y => 2 } ); my %hash2 = %hash1; print "hash1 before call\n"; print displayHash(\%hash1); print "hash2 before call\n"; print displayHash(\%hash2); fiddleHash(\%hash2); print "hash1 after call\n"; print displayHash(\%hash1); print "hash2 after call\n"; print displayHash(\%hash2);
The sub fiddleHash is only supposed to alter hash2 but it also alters hash1
Output:
hash1 before call y:2 x:1 hash2 before call y:2 x:1 hash1 after call y:2 hash2 after call y:2

Replies are listed 'Best First'.
Re: changing copy of a hash changes original
by poj (Abbot) on Nov 13, 2014 at 18:11 UTC
Re: changing copy of a hash changes original
by CountZero (Bishop) on Nov 13, 2014 at 18:19 UTC
    Add print "$hash1{Quantity} - $hash2{Quantity}"; and you will see that they both have the same reference, in other words they are referencing the same anonymous hash.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: changing copy of a hash changes original
by 2teez (Vicar) on Nov 13, 2014 at 18:25 UTC

    The sub fiddleHash is only supposed to alter hash2 but it also alters hash1

    Since you use this my %hash2 = %hash1;, then do this

    print %hash2; print %hash1;
    Then you will see why!

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
      Many thanks
Re: changing copy of a hash changes original
by Anonymous Monk on Nov 14, 2014 at 09:59 UTC
    The problem is the hash copy because it's a shallow copy. %hash1 and %hash2 have a key by the name of 'Quantity' which happen to point to the same thing...namely {x=>1,x=>2}. In fact the fidleHash() sub doesn't change the hash which comes in as an argument, rather it changes the hash which the 'Quantity' key is pointing to. Insert the following two lines after copying the hash: my %hashCopy = %{$hash1{'Quantity'}} ; $hash2{'Quantity'} = \%hashCopy ; ...and you won't see the problem anymore. That way you also create a copy of what 'Quantity' points to.
Re: changing copy of a hash changes original
by locked_user sundialsvc4 (Abbot) on Nov 14, 2014 at 14:43 UTC

    This is the difference between a so-called “shallow copy” and a “deep” one.   Perl has the concept of references, which are scalar-things which “refer to” other things.   (This is, by the way, how Perl appears to have “multi-dimensional,” even arbitrary, data-structures given that it actually only has scalars, lists, arrays, and hashes.)   It is easy to “copy” something such that what you’re actually doing is creating a structure of references to the original thing ... easy, memory-efficient, and it usually works great.   This is a “shallow” copy.