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

Can someone enlighten me? In the below code snippet. Why does changing $h3 change $h4 as well?
my %h1 = ( k1 => "v1" ); my %h2 = ( k2 => \%h1 ); my %h3 = ( k3 => \%h2 ); my %h4 = %h3; print "h3\n"; foreach my $i ( keys %h3 ) { print "$i => $h3{$i}\n"; foreach my $j (keys %{$h3{$i}}) { print " $j => $h3{$i}{$j}\n"; foreach my $k ( keys %{$h3{$i}{$j}}) { print " $k => $h3{$i}{$j}{$k}\n"; } } } $h3{k3}{k2}{k1} = "v2"; print "h4\n"; foreach my $i ( keys %h4 ) { print "$i => $h4{$i}\n"; foreach my $j (keys %{$h4{$i}}) { print " $j => $h4{$i}{$j}\n"; foreach my $k ( keys %{$h4{$i}{$j}}) { print " $k => $h4{$i}{$j}{$k}\n"; } } }

Replies are listed 'Best First'.
Re: Why is this
by ikegami (Patriarch) on Dec 09, 2011 at 01:46 UTC

    You don't have variables named $h3 or $h4. You probably mean %h3 and %h4.

    You don't change variable %h3. You change an element of %h1 using a reference stored in %h2 and another reference stored in %h3.

    $h3{k3}{k2}{k1} = "v2"; %h3 +--------------------+ | +----------+ | | k3 => | Ref -------------+ | +----------+ | | +--------------------+ | | %h4 | +--------------------+ | | +----------+ | | | k3 => | Ref -----------+ | | +----------+ | | | +--------------------+ | | | | v v %h2 +--------------------+ | +----------+ | | k2 => | Ref -----------+ | +----------+ | | +--------------------+ | | v %h1 +--------------------+ | +----------+ | | k1 => | Str "v2" | | | +----------+ | +--------------------+

    You can use Storable's dclone to do a "deep" (recursive) copy, in which case you'll end up with the following:

    %h3 +--------------------+ | +----------+ | | k3 => | Ref ------------+ | +----------+ | | +--------------------+ | | v %h2 +--------------------+ | +----------+ | | k2 => | Ref -----------+ | +----------+ | | +--------------------+ | | v %h1 +--------------------+ | +----------+ | | k1 => | Str "v2" | | | +----------+ | +--------------------+ %h4 +--------------------+ | +----------+ | | k3 => | Ref ------------+ | +----------+ | | +--------------------+ | | v %anon +--------------------+ | +----------+ | | k2 => | Ref -----------+ | +----------+ | | +--------------------+ | | v %anon +--------------------+ | +----------+ | | k1 => | Str "v1" | | | +----------+ | +--------------------+
      Thanks, I'm really impressed with the answer.
Re: Why is this
by locked_user sundialsvc4 (Abbot) on Dec 09, 2011 at 14:41 UTC

    Yup, ikegami is one of the best.

    When I read the node-title, and having been bit by the same darned thing before (and having asked for Enlightenment because I just couldn’t see it), it immediately jumped into my head:   “references.”

    One of the semantic weaknesses of Perl, so to speak, is that variables are basically un-typed, and that the runtime behavior of a particular piece of code is determined at runtime.   There is no way to express that a variable is, or that it must be, “a reference to this-or-that.”   In this particular language, at this particular time, the concept simply does not exist.   And it will bite you sometimes.   Two variables can be (to improperly borrow the FORTRAN term) effectively EQUIVALENCEd, just by a coincidence of whatever execution-path lead up to them being that way.   And there will be no “syntax error” or what-have-you to give you a heads-up about it.   (I don’t mean that as Perl Bashing, of course.   It’s just a peculiarity to be mindful of.

      There is no way to express that a variable is, or that it must be, "a reference to this-or-that."

      You can code it yourself, of course:

      ref($x) eq 'HASH' or die "D'oh! \$x must be a hash!";
      For more robust solutions, there are (of course) modules on CPAN, such as Data::Validate, Params::Validate, Sub::Contract, and Arguments, among many others. (Note that some only work for validating arguments to subroutines. Often this is all you need.)

      I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
      There is no way to express that a variable is, or that it must be, “a reference to this-or-that.” In this particular language, at this particular time, the concept simply does not exist. And it will bite you sometimes.
      Sure, but how would that have helped the OP? Even if he had the opportunity that declare that the values of %h3 and %h3 where references to hashes, it would not have prevented the OP getting confused.

      IMO, the OPs misunderstand had nothing at all to do with Perl have untyped variables. (Note BTW, that while Perls variables are untyped, its values are not).