Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl argument modification without references

Tags:

perl

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";

Output:

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";
}

Output :

Trying to change ...
Second
First

Why is this thing different in the two cases?

like image 623
Subhayan Bhattacharya Avatar asked Jul 29 '26 19:07

Subhayan Bhattacharya


1 Answers

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;

output

Before: { First => 1, Second => 2 }
After:  { First => 1, Second => 100 }
like image 106
Borodin Avatar answered Aug 01 '26 14:08

Borodin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!