Ответов (5)5
Это объясняется в документации Perl .
Из-за приоритета оператора Perl оператор анализируется как
($condition ? $a= 2 : $a ) = 3 ;
Поскольку оператор?: Дает назначаемый результат, результату условия присваивается 3.
Когда условие $ истинно, это означает ($ a = 2) = 3, что дает $ a = 3
Когда $ condition ложно, это означает ($ a) = 3, что дает $ a = 3
Правильный способ написать это
$a = ( $condition ? 2 : 3 );
print $a;
Нас это укусило на работе, поэтому я пишу здесь, надеясь, что другие сочтут это полезным.
Просто чтобы расширить предыдущий ответ ... Если по какой-либо причине назначения должны быть частью условного оператора, вы захотите написать его так:
$condition ? ($a=2) : ($a=3);
Это было бы полезно, если вы назначаете разные переменные в зависимости от условия.
$condition ? ($a=2) : ($b=3);
И если вы выбираете переменную, но назначаете одно и то же, несмотря ни на что, вы даже можете сделать это:
($condition ? $a : $b) = 3;
Если у вас возникло подозрение, что у вас могут быть проблемы с приоритетом, попробуйте выяснить, что, по мнению Perl, вы имели в виду:
perl -MO=Deparse,-p -e '$condition ? $a= 2 : $a= 3 ; print $a;'
В вашем случае это покажет вам:
(($condition ? ($a = 2) : $a) = 3);
print($a);
-e syntax OK
... в этот момент вы должны сказать: «О, это все объясняет»!
Из-за приоритета оператора Perl оператор анализируется как:
($condition ? $a = 2 : $a ) = 3 ;
Поскольку оператор?: Дает назначаемый результат, результату условия присваивается 3.
Когда условие $ истинно, это означает, что $ a = 2 = 3, что дает $ a = 3
Когда $ condition ложно, это означает, что $ a = 3 дает $ a = 3
Правильный способ написать это
$a = $condition ? 2 : 3;
В общем, вам действительно следует избавиться от привычки использовать условные выражения для выполнения присваивания, как в исходном примере - это то, что приводит к тому, что Perl приобретает репутацию предназначенного только для записи.
Хорошее практическое правило состоит в том, что условные выражения предназначены только для простых значений, а не для выражений с побочными эффектами. Когда через восемь месяцев вам или кому-то другому понадобится прочитать этот код, вы бы предпочли, чтобы он читался так?
$x < 3 ? foo($x) : bar($y);
Или вот так?
if ($x < 3) {
$foo($x);
} else {
$bar($y);
}