Assigning a reference shares the same data, while copying a hash makes a separate top-level hash.

shallow copy A shallow copy duplicates the top-level container but not deeper nested values.

Shallow Copy and Mutation

new_status
shallow_copy_mutation.pl
Replay: real traced execution (multi-file project)
use strict;
use warnings;

my $new_status = "done";
my $original_ref = { status => "open" };
my $alias_ref = $original_ref;
my $copy_ref = { %{$original_ref} };

$alias_ref->{status} = $new_status;

my $original_status = $original_ref->{status};
my $copy_status = $copy_ref->{status};

print "new_status=$new_status\n";
print "original=$original_status\n";
print "copy=$copy_status\n";
use strict;
use warnings;

my $new_status = "hold";
my $original_ref = { status => "open" };
my $alias_ref = $original_ref;
my $copy_ref = { %{$original_ref} };

$alias_ref->{status} = $new_status;

my $original_status = $original_ref->{status};
my $copy_status = $copy_ref->{status};

print "new_status=$new_status\n";
print "original=$original_status\n";
print "copy=$copy_status\n";
use strict;
use warnings;

my $new_status = "ready";
my $original_ref = { status => "open" };
my $alias_ref = $original_ref;
my $copy_ref = { %{$original_ref} };

$alias_ref->{status} = $new_status;

my $original_status = $original_ref->{status};
my $copy_status = $copy_ref->{status};

print "new_status=$new_status\n";
print "original=$original_status\n";
print "copy=$copy_status\n";
  1. $new_status ← done, $original_status ← done, $copy_status ← open

    4my $new_status→ done = "done"; #@new_status="hold", "ready"5my $original_ref = { status => "open" };6my $alias_ref = $original_ref;7my $copy_ref = { %{$original_ref} };89$alias_ref->{status} = $new_statusdone;1011my $original_status→ done = $original_ref->{status};12my $copy_status→ open = $copy_ref->{status};1314print "new_status=$new_statusdone\n";15print "original=$original_statusdone\n";16print "copy=$copy_statusopen\n";
    outputnew_status=done
    original=done
    copy=open
  1. $new_status ← hold, $original_status ← hold, $copy_status ← open

    4my $new_status→ hold = "hold";5my $original_ref = { status => "open" };6my $alias_ref = $original_ref;7my $copy_ref = { %{$original_ref} };89$alias_ref->{status} = $new_statushold;1011my $original_status→ hold = $original_ref->{status};12my $copy_status→ open = $copy_ref->{status};1314print "new_status=$new_statushold\n";15print "original=$original_statushold\n";16print "copy=$copy_statusopen\n";
    outputnew_status=hold
    original=hold
    copy=open
  1. $new_status ← ready, $original_status ← ready, $copy_status ← open

    4my $new_status→ ready = "ready";5my $original_ref = { status => "open" };6my $alias_ref = $original_ref;7my $copy_ref = { %{$original_ref} };89$alias_ref->{status} = $new_statusready;1011my $original_status→ ready = $original_ref->{status};12my $copy_status→ open = $copy_ref->{status};1314print "new_status=$new_statusready\n";15print "original=$original_statusready\n";16print "copy=$copy_statusopen\n";
    outputnew_status=ready
    original=ready
    copy=open