A precidência em Perl pode te surpreender …. me pegou!
Tenho um script que envia por e-mail alguns resultados para um assinante diariamente. Se não houver resultados, ele não envia um e-mail ao usuário – você só recebe um e-mail se houver algo para ver, em outras palavras.
Como um lembrete, o script enviará por e-mail um lembrete de inscrição para o usuário no primeiro dia do mês … mas apenas se ele não tiver recebido um e-mail com os resultados naquele dia.
O código era mais ou menos assim:
my $has_emailed = email($recipient, $data);
my @t = localtime;
if ( not $has_emailed && not $t[3] ) {
my $text = get_reminder_message();
email( $recipient, $text);
}
O problema era que eu estava enviando um lembrete por e-mail todos os dias!
Por quê? Precidência .
O &&
é um “e em curto-circuito” e tem uma precedência mais alta que o not
. Isso significa que a declaração realmente é lida como:
if ( not ($has_emailed && not $t[3]) )
então, seguindo a lógica, obtemos:
$t[3]
é o dia do mês, começando em 0 – FALSO para o primeiro dia e VERDADEIRO para todos os diasnot $t[3]
é, portanto, TRUE no primeiro dia, e FALSE em dias alternados$has_emailed
é TRUE se os resultados foram enviados para um usuário, FALSE se não …. estamos assumindo FALSE aqui($has_emailed && not $t[3])
é, portanto, FALSEnot ($has_emailed && not $t[3])
torna-se verdade.
Existem várias soluções:
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