Присвоение внутри задач тернарного условного оператора Perl
-
08-06-2019 - |
Вопрос
Этот фрагмент кода Perl в моей программе дает неправильный результат.
$condition ? $a = 2 : $a = 3 ;
print $a;
Неважно, какова ценность $condition
то есть на выходе всегда 3, почему?
Решение
Это объяснено в Perl документация.
Из-за приоритета операторов Perl оператор анализируется как
($condition ? $a= 2 : $a ) = 3 ;
Поскольку ?:Оператор выдает назначаемый результат, результату условия присваивается 3.
Когда $condition истинно, это означает ($a=2)=3, что дает $a=3.
Когда $condition ложно, это означает ($a)=3, что дает $a=3.
Правильный способ написать это
$a = ( $condition ? 2 : 3 );
print $a;
Нас это укусило на работе, поэтому я публикую здесь, надеясь, что другим это будет полезно.
Другие советы
Если у вас возникло подозрение, что вы можете страдать от проблем с приоритетом, есть трюк, позволяющий понять, что, по мнению Perl, вы имели в виду:
perl -MO=Deparse,-p -e '$condition ? $a= 2 : $a= 3 ; print $a;'
В вашем случае это покажет вам:
(($condition ? ($a = 2) : $a) = 3);
print($a);
-e syntax OK
... в этот момент вы должны сказать: «О, это объясняет»!
Просто чтобы расширить предыдущий ответ...Если по какой-либо причине присваивания должны быть частью условия, вы можете написать это так:
$condition ? ($a=2) : ($a=3);
Это было бы полезно, если вы назначаете разные переменные в зависимости от условия.
$condition ? ($a=2) : ($b=3);
А если вы выбираете переменную, но назначаете одно и то же, несмотря ни на что, вы можете сделать это:
($condition ? $a : $b) = 3;
Из-за приоритета операторов Perl оператор анализируется как:
($condition ? $a = 2 : $a ) = 3 ;
Поскольку ?:Оператор выдает назначаемый результат, результату условия присваивается 3.
Когда $condition истинно, это означает, что $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);
}
Одно предложение к ответу Титония выше:
Если вы хотите присвоить разные значения одной и той же переменной, это может быть лучше (способ прописи):
$а = ($условие) ?2:3;