0

I'm creating keys outside and inside a subroutine on the same hash. However, after the subroutine, the values in the keys I created before the subroutine is called, are now interpreted as array references.

#!/usr/bin/perl
use module;
use strict;
use warnings;
my %hash;
my $count = 0;

my @array = ("a", "b", "c", "d");

for my $letter (@array) {
    $hash{$letter} = $count;
    $count++;
}

# need "\" to pass in hash otherwise changes
# will get lost outside of subroutine
foreach my $x (sort keys %hash) {
    print "first $hash{$x}\n";
}

module::add_ten(\%hash);

foreach my $p (sort keys %hash) {
    # $hash{$p} is printing array references, but before it was
    # printing the value I desired.  What did the subroutine do?
    print "second $hash{$p} $hash{$p}->{ten}\n";
}

and here is the module with the subroutine

package module;

sub add_ten {
my $count = 10;
    # this passes the full array as reference
    my ($hash_ref) = @_; # $hash_ref is actually %hash (yes, the % is not a typo)
    my @keys = keys $hash_ref;
    foreach my $ltr (sort keys $hash_ref) {
        $hash_ref->{$ltr} = { ten => $count };
        $count++;
    }
}
1;

here is the output:

first 0
first 1
first 2
first 3
second HASH(0x7ff0c3049c50) 10
second HASH(0x7ff0c3049bc0) 11
second HASH(0x7ff0c3049b90) 12
second HASH(0x7ff0c3049b60) 13

I'm expecting the output to be:

first 0
first 1
first 2
first 3
second 0 10
second 1 11
second 2 12
second 3 13

I modified my module:

package module;

sub add_ten {
    my $count = 10;
    # this passes the full array as reference
    my ($hash_ref) = @_; # $hash_ref is actually %hash (yes, the % is not a typo)
    my @keys = keys $hash_ref;
    foreach my $ltr (sort keys $hash_ref) {
        $hash_ref->{$ltr}{ten}=$count;
        $count++;
    }
}
1;

and the main script (needed to comment out use strict to get it to work):

#!/usr/bin/perl
use module;
#use strict;
use warnings;
my %hash;
my $count = 0;

my @array = ("a", "b", "c", "d");

for my $letter (@array) {
    $hash{$letter} = $count;
    $count++;
}

# need "\" to pass in hash otherwise changes
# will get lost outside of subroutine
foreach my $x (sort keys %hash) {
    print "first $hash{$x}\n";
}

module::add_ten(\%hash);

foreach my $p (sort keys %hash) {
    print "second $hash{$p} $hash{$p}{ten}\n";
}

But this is what I was trying to get to.

2
  • That comment should read %$hash_ref is %hash Commented Jul 4, 2015 at 0:51
  • 1
    use module should be use Module, and the module itself should be in Module.pm and contain a package statement package Module Commented Jul 4, 2015 at 10:41

1 Answer 1

4

$hash_ref is a reference to %hash, so when you change the values of the elements of the hash referenced by $hash_ref, you're changing the values of the hash %hash.

That means that when you do

 $hash_ref->{$ltr} = { ten => $count };

You are doing

 $hash{a} = { ten => 10 };

It should be no surprise that $hash{a} no longer contains zero. You'll have to change your data structure. You could use the following:

$hash{a}{value} = 0;
$hash{a}{subhash}{ten} = 10;
Sign up to request clarification or add additional context in comments.

4 Comments

I want $hash{a} = 0 and $hash{a}{ten} = 10. But $hash{a} returns a hash reference after the subroutine (which I don't want), before the subroutine $hash{a} returned "0"
You are doing $hash{a} = 0; $hash{a} = \%subhash;, and asking why $hash{a} isn't zero. It can only hold one of those two values at a time.
Added a solution to my answer.
I see... I thought I was adding another element to $hash{a} called "ten" such that the new data structure would look like $hash{a}{ten}=10.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.