Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning about void context only with low-precedence short-circuit operators

Tags:

perl

I just encountered a situation where and and && behave differently with respect to warnings.

Here's the original script with and.

#!/usr/bin/env perl
use strict;
use warnings 'FATAL' => qw[all];

my $var1;
my $var2;

my $defined = (defined $var1) and (defined $var2);

print ($defined ? "defined\n" : "undefined\n");

because first condition is false, the second expression in the and is never evaluated.

% perl defined.pl
Useless use of defined operator in void context at defined.pl line 8.
Exit 255

However if I change the operation to the higher-precedence but otherwise identical &&, I don't get a void context warning.

#!/usr/bin/env perl
use strict;
use warnings 'FATAL' => qw[all];

my $var1;
my $var2;

my $defined = (defined $var1) && (defined $var2);

print ($defined ? "defined\n" : "undefined\n");

The program produces the expected result, "undefined\n".

% perl defined.pl
undefined

perldoc perlop suggests that and and && should be identical in all respects except for precedence, but does not explicitly state it.

As alternatives to && and || when used for control flow, Perl provides the and and or operators (see below). The short-circuit behavior is identical. The precedence of "and" and "or" is much lower, however, so that you can safely use them after a list operator without the need for parentheses:

like image 406
Gregory Nisbet Avatar asked Oct 04 '16 17:10

Gregory Nisbet


1 Answers

The assignment operator has a higher precedence than and, so

my $defined = (defined $foo) and (defined $bar);

is equivalent to

(my $defined = (defined $foo)) && (defined $bar);

You can see this with B::Deparse:

$ perl -MO=Deparse -e'my $defined = (defined $foo) && (defined $bar)'                                                               
my $defined = defined $foo && defined $bar;
-e syntax OK

$ perl -MO=Deparse -e'my $defined = (defined $foo) and (defined $bar)'
defined $bar if my $defined = defined $foo;
-e syntax OK
like image 106
ThisSuitIsBlackNot Avatar answered Jan 01 '23 11:01

ThisSuitIsBlackNot