I just finished writing a test that discovered I’d made a rather dumb and (upon looking back) rather obvious mistake in a return value in this Perl application I’m working on. The mistake involves a certain errant combination of return and and must be dealt with carefully.
The particular bit of code looks something like this:
sub blah {
return $foo and $bar;
}
For those who don’t know Perl intimately, Perl has two “and” operators. One named “and” and the other named “&&” like C. These are not strict synonyms. They are both shortcut operators, but the “&&” and the “and” sit at very different places in the operator precedent order. In Perl “&&” has a relatively high precedent and “and” is very, very low.
Back to the problem: this return was returning true when $foo was true and $bar was false. After rereading this line I smacked my forehead and said, “Duh!” The problem is that “return” actually has a higher operator precedent than “and” so this is how Perl would break it out if it showed the AST with parenthesis:
sub blah {
(return $foo) and ($bar);
}
This means the code immediately return $foo in all circumstances. I might as well have just written:
sub blah {
return $foo;
}
The solution, then, is to either use the “&&” operator:
sub blah {
return $foo && $bar;
}
Or use explicit parenthesis:
sub blah {
return ($foo and $bar);
}
Or don’t use the “return” operator (since subroutines in Perl always return the value of the last expression executed):
sub blah {
$foo and $bar;
}
Cheers.
