I was just toying with the concept of modifying arguments inside a Perl subroutine without using references. I tried this in case of arrays :
sub test {
print "Trying to change ... \n";
$_[0] = "Third";
$_[1] = 100;
}
@a = ("First", 1, "Second", 2);
print "Before change : @a \n";
test(@a);
print "After change : @a \n";
Before change : First 1 Second 2
Trying to change ...
After change : Third 100 Second 2
In other words the elements of an array is changed by changing the values of @_.
But doing the same in case of hashes does not give the intended behavior:
sub test {
print "Trying to change ... \n";
$_[0] = "Third";
$_[1] = 100;
}
%h = ("First" => 1, "Second" => 2);
test(%h);
foreach ( keys %h ) {
print "$_\n";
}
Trying to change ...
Second
First
Why is this thing different in the two cases?
You have been slightly misled
Perl hash keys aren't ordinary Perl scalar values -- they are stored as a simple C string for speed, but hash values are Perl scalars
In a call like test(%h) Perl creates a temporary Perl scalar out of each hash key string and passes those, together with the real hash value scalars
That means that any attempt to modify the key strings will change only the temporary scalars, and won't be reflected in the hash. But your code does change the values
Here's a version that dumps the whole hash before and after the subroutine call. You can see that the string Third has been lost, but 100 has been assigned to a (random) hash value
use strict;
use warnings 'all';
use Data::Dump 'pp';
sub test {
$_[0] = "Third";
$_[1] = 100;
}
my %h = ("First" => 1, "Second" => 2);
printf "Before: %s\n", pp \%h;
test(%h);
printf "After: %s\n", pp \%h;
Before: { First => 1, Second => 2 }
After: { First => 1, Second => 100 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With