Perl одна строка, если оператор

У меня есть инструкция

$set eq "Y" ? $set = "N" : $set = "Y";

Но независимо от того, что он всегда устанавливает в "N"

# Toggle setting
if ($set eq "Y")
{
   $set = "N";
}
else
{
   $set = "Y";
}

Почему не работает один лайнер?

Ответ 1

Из-за правил приоритета perl не анализирует ваше утверждение, как вы думаете:

$ perl -MO=Deparse,-p -e '$set eq "Y" ? $set = "N" : $set = "Y"'
((($set eq 'Y') ? ($set = 'N') : $set) = 'Y');
-e syntax OK

Итак, как вы видите, в обоих условиях конечным результатом является скаляр $set, который затем получает значение Y.

Вы можете исправить это несколькими парами:

$set eq "Y" ? $set = "N" : ($set = "Y")

Но зачем повторять назначение:

$set = $set eq 'Y' ? 'N' : 'Y';

Ответ 2

Приоритет оператора. То, что вы написали, эквивалентно

($set eq "Y" ? $set = "N" : $set) = "Y";

Если вы настаиваете на написании такого краткого кода, это имеет смысл:

$set = ( $set eq "Y" ? "N" : "Y" );

Ответ 3

$set = ($set eq "Y") ? "N" : "Y";

должен работать

Ответ 4

Это о приоритете; сделайте намерение с помощью скобок, а затем пусть Perl удалит их снова:

perl -MO=Deparse -e '($set eq "Y") ? ($set = "N") : ($set = "Y"); print $set'
$set eq 'Y' ? $set = 'N' : ($set = 'Y');
print $set;
-e syntax OK

Который, таким образом, является скобкой, необходимой для выполнения, как вы планировали.

Ответ 5

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

my $set = "Y"; #Set the scope and default value
$set = "N" if ($set eq "Y");

Я лично рекомендую стиль "С", описанный другими выше... он легко демонстрирует две опции, которые может быть переменной.

Тем не менее, метод, который я показываю, хорош при работе с одним условным результатом.