40 votes

Problèmes d'affectation à l'intérieur d'un opérateur conditionnel ternaire en Perl

Ce bout de code Perl dans mon programme donne le mauvais résultat.

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

Quelle que soit la valeur de $condition est, la sortie est toujours 3, comment ça se fait ?

79voto

Pat Points 18943

Ceci est expliqué dans le manuel Perl documentation .

En raison de la précédence des opérateurs Perl, la déclaration est analysée comme suit

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

Comme l'opérateur ? : produit un résultat assignable, 3 est assigné au résultat de la condition.

Lorsque $condition est vrai, cela signifie que ($a=2)=3, ce qui donne $a=3.

Lorsque $condition est faux, cela signifie que ($a)=3, ce qui donne $a=3.

La façon correcte d'écrire ceci est

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

Nous avons été piqués par ce problème au travail, alors je le poste ici en espérant que d'autres personnes le trouveront utile.

40voto

theorbtwo Points 491

Une fois que vous avez une idée que vous pourriez souffrir de problèmes de précédence, une astuce pour comprendre ce que Perl a pensé que vous vouliez dire :

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

Dans votre cas, ça va vous montrer :

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

...à ce moment-là, vous devriez dire "oh, ça explique tout" !

21voto

Tithonium Points 484

Pour prolonger la réponse précédente... Si, pour une raison quelconque, les affectations doivent faire partie de la conditionnelle, vous voudrez l'écrire ainsi :

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

Cela peut être utile si vous affectez des variables différentes en fonction de la condition.

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

Et si vous choisissez la variable, mais que vous lui attribuez la même chose quoi qu'il arrive, vous pouvez même faire ça :

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

4voto

raldi Points 5114

En raison de la précédence des opérateurs Perl, la déclaration est analysée comme :

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

Comme l'opérateur ? : produit un résultat assignable, 3 est assigné au résultat de la condition.

Lorsque $condition est vrai, cela signifie que $a=2=3 donnant $a=3

Lorsque $condition est false cela signifie que $a=3 donnant $a=3

La façon correcte d'écrire ceci est

$a = $condition ? 2 : 3;

D'une manière générale, vous devriez vraiment perdre l'habitude d'utiliser des conditionnels pour faire des affectations, comme dans l'exemple original -- c'est le genre de chose qui fait que Perl a la réputation d'être réservé à l'écriture.

Une bonne règle de base est que les conditionnels ne sont destinés qu'aux valeurs simples, jamais aux expressions avec des effets secondaires. Lorsque vous ou quelqu'un d'autre devra lire ce code dans huit mois, préférerez-vous qu'il se lise comme ceci ?

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

Ou comme ça ?

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

0voto

Jagmal Points 1205

Une suggestion à la réponse de Tithonium ci-dessus :

Si vous souhaitez attribuer différentes valeurs à la même variable, cette méthode est peut-être la meilleure (la méthode du livre de poche) :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X