Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl modifying hash reference in subroutine

I am having trouble understanding the hash references and changing the hash in place, instead of returning it. I want to write a sub routine which will return a value from hash and also modify the hash. I was facing some issues while coding for it. So, I wrote the following basic code to understand modifying the hash in place.

#!/usr/local/bin/perl
#Check hash and array references
#Author: Sidartha Karna
use warnings;
use strict;
use Data::Dumper;

sub checkHashRef{
   my ($hashRef, $arrVal) = @_;
   my %hashDeref = %{$hashRef};

   $hashDeref{'check'} = 2;           
   push(@{$arrVal}, 3);

   print "There:" ;
   print Dumper $hashRef;      
   print Dumper %hashDeref;           
   print Dumper $arrVal

}


my %hashVal = ('check', 1);
my @arrVal = (1, 2);

checkHashRef(\%hashVal, \@arrVal);

print "here\n";
print Dumper %hashVal;
print Dumper @arrVal;

The output observed is:



    There:$VAR1 = {
          'check' => 1
        };
    $VAR1 = 'check';
    $VAR2 = 2;
    $VAR1 = [
          1,
          2,
          3
        ];
    here
    $VAR1 = 'check';
    $VAR2 = 1;
    $VAR1 = 1;
    $VAR2 = 2;
    $VAR3 = 3;

From the output, I inferred that, changes to hashDeref are not modifying the data in the reference. Is my understanding correct? Is there a way to modify the hash variable in place instead of returning it.

like image 241
Sid Avatar asked Apr 13 '12 05:04

Sid


People also ask

How to dereference a hash reference in Perl?

In order to dereference, we use the prefix $, @, % or & depending on the type of the variable(a reference can point to a array, scalar, or hash etc).

Is Perl pass by reference?

Perl always passes by reference. It's just that sometimes the caller passes temporary scalars. Perl passes by reference. Specifically, Perl aliases each of the arguments to the elements of @_ .


1 Answers

This is making a (shallow) copy of %hashVal:

my %hashDeref = %{$hashRef};

The hash-ref $hashRef still points to %hashVal but %hashDeref doesn't, it is just a copy. If you want to modify the passed hash-ref in-place, then work with the passed hash-ref:

sub checkHashRef{
   my ($hashRef, $arrVal) = @_;
   $hashRef->{'check'} = 2;
   #...

That will leave your changes in %hashVal. In the array case, you never make a copy, you just dereference it in-place:

push(@{$arrVal}, 3);

and the change to $arrVal shows up in @arrVal.

like image 108
mu is too short Avatar answered Nov 09 '22 23:11

mu is too short