Gregory Nisbet Gregory Nisbet - 2 months ago 6
Perl Question

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

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 lower-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:

Answer

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