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

Этот фрагмент кода Perl в моей программе дает неверный результат.

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

Независимо от того, что значение $condition, выход всегда 3, как получится?

12.08.2008 16:03:54
5 ОТВЕТОВ
РЕШЕНИЕ

Это объясняется в документации по Perl .

Из-за приоритета оператора Perl оператор анализируется как

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

Поскольку оператор?: Производит присваиваемый результат, 3 присваивается результату условия.

Когда $ условие истинно, это означает ($ a = 2) = 3, давая $ a = 3

Когда $ условие ложно, это означает, что ($ a) = 3 дает $ a = 3

Правильный способ написать это

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

Это нас укусило на работе, поэтому я пишу здесь, надеясь, что другие найдут это полезным.

79
13.10.2008 13:03:39
«Когда $ условие истинно, это означает, что $ a = 2 = 3 дает $ a = 3». Я бы подумал, что $ a = 2 = 3 будет ошибкой синтаксиса выражения или ошибкой, необходимой для lvalue, или чем-то подобным ... Как именно это получается оценивать?
sundar - Reinstate Monica 11.10.2008 13:08:43
Вы правы, я изменю это ($ a = 2) = 3 вместо $ a = 2 = 3
Pat 13.10.2008 13:02:04

Просто для продолжения предыдущего ответа ... Если по какой-либо причине назначения должны быть частью условного выражения, вы бы хотели написать его так:

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

Это было бы полезно, если вы назначаете разные переменные в зависимости от условия.

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

И если вы выбираете переменную, но присваиваете одно и то же, несмотря ни на что, вы можете даже сделать это:

($condition ? $a : $b) = 3;
21
22.08.2008 04:58:03

Одно предложение к ответу Tithonium выше:

Если вы хотите присвоить разные значения одной и той же переменной, это может быть лучше (способ тетради):

$ a = ($ условие)? 2: 3;

0
4.09.2008 12:54:51

Если у вас есть подозрение, что вы можете страдать от проблем с приоритетом, уловка, чтобы выяснить, что Perl думал, что вы имели в виду:

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

В вашем случае это покажет вам:

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

... в этот момент вы должны сказать "о, это объясняет"!

40
11.10.2008 11:55:03
Deparse - очень аккуратный трюк на вечеринке. Конечно, как только вы заподозрили проблему приоритета, вы, как правило, находите большую часть пути к ее решению ;-)
RET 22.09.2008 06:56:32

Из-за приоритета оператора Perl оператор анализируется как:

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

Поскольку оператор?: Производит присваиваемый результат, 3 присваивается результату условия.

Когда $ условие истинно, это означает, что $ a = 2 = 3, давая $ a = 3

Когда $ условие ложно, это означает, что $ a = 3 дает $ a = 3

Правильный способ написать это

$a = $condition ? 2 : 3;

В общем, вы действительно должны отказаться от привычки использовать условные выражения для выполнения присваивания, как в первоначальном примере - это та вещь, которая приводит к тому, что Perl получает репутацию только для записи.

Хорошее практическое правило заключается в том, что условные выражения предназначены только для простых значений, а не выражений с побочными эффектами. Когда вам или кому-либо еще нужно прочитать этот код через восемь месяцев, вы бы предпочли, чтобы он читался так?

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

Или вот так?

if ($x < 3) {
  $foo($x);
} else {
  $bar($y);
}
4
16.09.2008 16:39:28