Reputation: 41
We've got some legacy code throwing up the "Can't use a hash as a reference" perl error. The previous "fix" was to turn off warnings, but new perl has made the warning a hard error and so now someone's got to actually fix the problem.
The code looks like this...
foreach my $a (keys %{$x->{'y'}}) {
my $b = %$x->{'y'}->{$a};
<some other stuff>
}
My understanding is that something like %j->{'k'} should be converted into $j{'k'}, but the %$ thing with two pointers is more than I can process, given that I only understand this at the most general of levels.
It seems that only the line within the loop is causing the error, but I included the foreach for reference.
Is it clear what the original author is attempting to do and is there an obvious fix that that will clean this up once and for all?
Thanks.
Upvotes: 2
Views: 2817
Reputation: 85767
It looks like the idea is to iterate over the entries in the hash referenced by $x->{'y'}
. The foreach
loop sets $a
to each key in turn. The loop body would then assign the corresponding value to $b
.
From the keys
expression we can see that $x
must contain a reference to a hash, and that the value under the key 'y'
must be a reference to another hash. From that you can get the value under $a
by doing
my $b = $x->{'y'}->{$a};
# or:
my $b = $x->{y}{$a}; # if you don't like typing
The problem with your original code is the %$x->{...}
part. %$x
dereferences the reference in $x
, so what you get as a result is an actual hash. The ->{...}
operator then tries to dereference it again, which makes no sense (as the error message says, a hash is not a reference). Just drop the %
and let ->{...}
do the work.
(Alternatively, if you're feeling crazy, you can do (\%$x)->{'y'}->{$a}
. In addition to %
(to dereference the reference in $x
), we use \
(to take a reference to the hash we just got), which can then correctly be dereferenced (again) by ->{...}
.)
For the future, blindly silencing warnings is usually not a good idea, especially if they tell you about bugs in your code.
Upvotes: 1
Reputation: 98398
Just dropping the % should do it. I can't imagine anything else that could have been meant.
Upvotes: 4