Reputation: 497
I'm trying to return a reference to a hash from a string value but the results depends on the order of when the hash and sub are defined.
Snippet 1:
my $uid = { '199' => 'Twister', '396' => 'Khorus', '450' => 'Ling', '555' => 'Sage' };
sub href { eval "\$$_[0]" }
print Dumper href('uid');
Output of snippet 1:
$VAR1 = {
'199' => 'Twister',
'396' => 'Khorus',
'450' => 'Ling',
'555' => 'Sage'
};
Snippet 2:
sub href { eval "\$$_[0]" }
my $uid = { '199' => 'Twister', '396' => 'Khorus', '450' => 'Ling', '555' => 'Sage' };
print Dumper href('uid');
Output of snippet 2:
$VAR1 = undef;
It shouldn't matter if the sub is defined before or after the hash but it does. What am I missing?
Upvotes: 0
Views: 83
Reputation: 385496
The whole point of using my
to is limit the scope (visibility) of variables. my
variables are scoped from the statement after which they are created to the end of the innermost block in which they are located, which means they are only visible to that code. (The file itself acts as a block.)
# This code can't see $x.
my $x;
# This code can see $x.
{
# This code can't see $y.
my $y;
# This code can see $y.
}
# This code can't see $y.
To be clear, this is strictly based on where the code is located in the source; it's not based on when code is executed.
As such, my $uid
needs to be found before the sub's declaration in order for the sub to see the variable. You can always set its value later, however.
That said, what you are doing is horrible! You are intentionally doing the very thing we force ourselves to not do by using use strict;
in every program! See Why it's stupid to `use a variable as a variable name' and A More Direct Explanation of the Problem.
Instead, replace
my $uid;
sub href { eval "\$$_[0]" }
$uid = { '199' => 'Twister', '396' => 'Khorus', '450' => 'Ling', '555' => 'Sage' };
with
my %data;
sub href { $data{$_[0]} }
$data{uid} = { '199' => 'Twister', '396' => 'Khorus', '450' => 'Ling', '555' => 'Sage' };
Upvotes: 2