Pergunta

Este trecho de código Perl no meu programa está dando o resultado errado.

$condition ? $a = 2 : $a = 3 ;
print $a;

Não importa qual seja o valor $condition é, a saída é sempre 3, como assim?

Foi útil?

Solução

Isso é explicado no Perl documentação.

Devido à precedência do operador Perl, a instrução está sendo analisada como

($condition ? $a= 2 : $a ) = 3 ;

Porque o ?:operador produz um resultado atribuível, 3 é atribuído ao resultado da condição.

Quando $condição é verdadeira, isso significa ($a=2)=3 dando $a=3

Quando $condição é falsa, isso significa ($a)=3 dando $a=3

A maneira correta de escrever isso é

$a = ( $condition ? 2 : 3 );
print $a;

Fomos afetados por isso no trabalho, por isso estou postando aqui esperando que outros considerem isso útil.

Outras dicas

Assim que você tiver a ideia de que pode estar sofrendo de problemas de precedência, um truque para descobrir o que Perl achou que você quis dizer:

perl -MO=Deparse,-p -e '$condition ? $a= 2 : $a= 3 ; print $a;'

No seu caso, isso mostrará:

(($condition ? ($a = 2) : $a) = 3);
print($a);
-e syntax OK

... nesse ponto você deveria estar dizendo "ah, isso explica tudo"!

Apenas para estender a resposta anterior ...Se, por qualquer motivo, as atribuições precisarem fazer parte da condicional, você desejaria escrevê-las assim:

$condition ? ($a=2) : ($a=3);

Isso seria útil se você estivesse atribuindo variáveis ​​diferentes com base na condição.

$condition ? ($a=2) : ($b=3);

E se você estiver escolhendo a variável, mas atribuindo a mesma coisa de qualquer maneira, você pode até fazer isso:

($condition ? $a : $b) = 3;

Devido à precedência do operador Perl, a instrução está sendo analisada como:

($condition ? $a = 2 : $a ) = 3 ;

Porque o ?:operador produz um resultado atribuível, 3 é atribuído ao resultado da condição.

Quando $condição é verdadeira, isso significa $a=2=3 dando $a=3

Quando $condição é falsa, isso significa $a=3 dando $a=3

A maneira correta de escrever isso é

$a = $condition ? 2 : 3;

Em geral, você realmente deve abandonar o hábito de usar condicionais para fazer atribuições, como no exemplo original - é o tipo de coisa que faz com que o Perl ganhe a reputação de ser somente gravação.

Uma boa regra é que as condicionais são apenas para valores simples, nunca para expressões com efeitos colaterais.Quando você ou outra pessoa precisar ler este código daqui a oito meses, você preferiria que fosse lido assim?

$x < 3 ? foo($x) : bar($y);

Ou assim?

if ($x < 3) {
  $foo($x);
} else {
  $bar($y);
}

Uma sugestão para a resposta do Tithonium acima:

Se você deseja atribuir valores diferentes à mesma variável, isso pode ser melhor (do jeito do copybook):

$a = ($condição)?2:3;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top