Присвоение внутри задач тернарного условного оператора Perl

StackOverflow https://stackoverflow.com/questions/9009

Вопрос

Этот фрагмент кода 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;

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top