Last Updated: February 25, 2016
·
188
· perllaghu

# The joys of precidence

Precidence in Perl can catch you out.... it caught me out!

I have a script which emails some results to a subscriber on a daily basis. If there are no results, then it doesn't email the user - you only get an email if there's something to see, in other words.
As a reminder, the script will email a subscription-reminder to the user on the 1st of the month..... but only if they haven't been sent a results email that day.

The code went something like this:

``````my \$has_emailed = email(\$recipient, \$data);
my @t = localtime;
if ( not \$has_emailed && not \$t[3] ) {
my \$text = get_reminder_message();
email( \$recipient, \$text);
}``````

The problem was that this was emailing a reminder every day!

Why? Precidence.

The `&&` is a "short-circuiting and", and has a higher precedence that the `not`. This means that the statement actually reads as:

``if ( not (\$has_emailed && not \$t[3]) )``

so following the logic, we get:

• `\$t[3]` is the day-of-the-month, starting at 0 - FALSE for the 1st, and TRUE for every other day
• `not \$t[3]` is therefore TRUE on the 1st, and FALSE every other day
• `\$has_emailed` is TRUE if results were went to a user, FALSE if not.... we're assuming FALSE here
• `(\$has_emailed && not \$t[3])` is therefore FALSE
• `not (\$has_emailed && not \$t[3])` becomes true.

There are a number of solutions:

``````if ( (not \$has_emailed) && (not \$t[3]) ) {...} # Be explicit where the not's go
if ( !\$has_emailed && !\$t[3] )           {...} # ! has a higher precedence that &&
if ( \$has_emailed || \$t[3] ) {}   else   {...} # cast the problem into the negative
unless ( \$has_emailed || not\$t[3] ))     {...} # Perl::Critic doesn't like unless``````

24.47K
13

17.12K
2

### Easily parse XML with Perl

14.1K
0

#### Have a fresh tip? Share with Coderwall community!

Best #Perl Authors
ksi
25.06K
janosgyerik
24.92K
syxanash
13.99K
creaktive
11.84K
Awesome Job