Useless use of hash element in void context
Among the many warnings of Perl that might, or might not indicate a bug, this certainly points to code that was written incorrectly.
If we run this script:
examples/hash_with_or.pl
use strict; use warnings; my %h = ( a => 1, b => 2, ); my $r = $h{a} or $h{b};
We get: Useless use of hash element in void context
The same is true if we use HASH references:
examples/hashref_with_or.pl
use strict; use warnings; my $x = { a => 1, b => 2, }; my $r = $x->{a} or $x->{b};
The problem was probably created when the author of this code wanted to set a default value. That is the author wanted to set $r to be equal to $h{a}, but if that key did not exist, or if its value was undef then she wanted to set $r to be $h{b}.
Unfortunately the snippet to set default value uses || and not or.
The reason for that is that || is higher in the precedence table than = which
is higher than or. So the correct code would have been:
or in a more idiomatic way:
Probably even better to use the defined-or operator:
that was introduced in Perl 5.10.
If you did not know the above and could not find an article explaining it, you could always
ask Perl to tell you what does it think about a piece of code. For this you can usually use
B::Deparse with the -p flag
to add extra parentheses.
In our case this is what we get:
Here you can see that B::Deparse added parentheses around the assignment (my $r = $h{'a'})
which means that will be executed first and then there is a dangling extra code: or $h{'b'}
that has no impact on anything. That's why Perl warns you about useless use.
The correct way to write this would be to write this:
examples/hash_with_or_fixed.pl
I have been bitten by this, as I tend to default to “or” because it is lower precedence, which often is desired, as in this case:
open FH, $file or die “Cannot open file $file”;
If you use || instead of “or”, the double pipe resolves first, and so will return true for a non-empty file. But since “or” has a lower precedence than comma, if you use “or”, it will execute as expected.
Note that confusion between “or” and || can be avoided enforcing precedence with parentheses, by writing:
open ( FH, $file ) || die “Cannot open file $file”;
making parentheses a good standard practice in my book.
I think a thorough discussion of this in the Beginner Perl Maven e-book would be an excellent addition (if it is not already there).
my $r = ($h{a} or $h{b});
my $r = $h{a} || $h{b};
my $r = $h{a} // $h{b};
B::Deparse
perl -MO=Deparse,-p examples/hash_with_or.pl
Useless use of hash element in void context at examples/hash_with_or.pl line 9.
use warnings;
use strict;
(my(%h) = ('a', 1, 'b', 2));
((my $r = $h{'a'}) or $h{'b'});
use strict;
use warnings;
my %h = (
a => 1,
b => 2,
);
my $r = $h{a} // $h{b};
Comments
Published on 2018-04-08