Назначение с использованием тернарного оператора?

Я на Perl 5.8, и мне нужно присвоить значение по умолчанию. Я закончил это:

if ($model->test) {
    $review = "1"
} else {
    $review = ''
}

Значение $model->test будет либо "1", либо undefined. Если есть что-то в $model->test, установите $review в "1", иначе установите его равным ''.

Потому что это не Perl 5.10 Я не могу использовать новый swanky defined-or operator. Моя первая реакция заключалась в том, чтобы использовать тернарный оператор, как это...

defined($model->test) ? $review = "1" : $review = '';

но это тоже не сработало.

Есть ли у кого-нибудь идея, как назначить это более эффективно? Джени

Обычно я пишу это как:

$review = ( defined($model->test) ? 1 : '' );

где скобки для ясности для других людей, читающих код.

32
ответ дан 19 янв. '12 в 23:54
источник

У вас проблема с приоритетом. То, что у вас есть, такое же, как

( defined($model->test) ? $review="1" : $review ) = '';

Вы можете заставить его работать с parens.

my $review; $model->test ? ( $review='1' ) : ( $review='' );

Но гораздо проще вывести назначение.

my $review = $model->test ? '1' : '';

Конечно, вы могли бы просто использовать

my $review = $model->test || '';

Но зачем менять undef на пустую строку?

my $review = $model->test;
19
ответ дан 20 янв. '12 в 0:26
источник

$model->test будет либо "1", либо undefined. Если есть что-то в $model->test, установите $review в "1", иначе установите его ''

Тогда просто используйте это:

$review = $model->test || "";
9
ответ дан 20 янв. '12 в 0:12
источник

Помимо условного оператора, мне часто нравится использовать do, который возвращает значение из последнего вычисленного выражения:

my $review = do {
     if( ... ) { 'foo' }
  elsif( ... ) { 'bar' }
  elsif( ... ) { 'baz' }
  else         { 'defaut' }
  };
7
ответ дан 22 авг. '13 в 22:59
источник

Прежде всего, "Это тоже не сработало" - это не самая полезная вещь, которую вы могли бы нам рассказать. Важно точно знать, как это не сработало: что он сделал, чего вы ожидали и как они отличаются?

Но проблема с

defined($model->test) ? $review="1" : $review='';

- приоритет оператора. Условный оператор ? : связывается сильнее, чем оператор присваивания =, поэтому приведенное выше эквивалентно:

(defined($model->test) ? $review="1" : $review) = '';

Итак, если $model->test определено, он выполняет эквивалент

$review = "1" = '';

Вы можете исправить эту проблему с помощью круглых скобок:

defined($model->test) ? ($review="1") : ($review='');

Но на самом деле, зачем вам это нужно? Условный (тернарный) оператор полезен, когда вы хотите использовать результат. Если результат будет отброшен, как он есть здесь, он станет более ясным (и, как вы видели, менее подверженным ошибкам), использовать инструкцию if/else:

if (defined($model->test) {
    $review = "1";
}
else {
    $review = "";
}

или, если вы настаиваете на записи его на одной строке:

if (defined($model->test) { $review = "1"; } else { $review = ""; }

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

$review = defined($model->test) ? "1" : "";

что, вероятно, является разумным способом сделать это.

НО:

Сам оператор defined дает либо "1" (true), либо "" (false). поэтому все это можно свести к:

$review = defined($model->test);
2
ответ дан 20 янв. '12 в 0:24
источник

Я предполагаю, что $model->test должен возвращать истинное или ложное значение.

Если в нем конкретно не указано, что ложное значение undef, этот метод можно переписать, чтобы вместо этого вернуть другое ложное значение. Который сломал бы все, что только проверяет, определено ли значение.
(Я думаю, что это ошибка, что метод возвращает undef вместо канонического ложного значения.)

Таким образом, лучший способ установить $review - проверить правдивость возвращаемого значения; не определенность.

my $review = $model->test ? 1 : '';

Я хотел бы указать, что в этом все еще есть ошибка. Если вы хотите использовать значение как число, оно будет выдавать предупреждения, если оно было ложным.

Чтобы исправить это, вы должны вернуть !1 (каноническое ложное значение), которое вернет значение, которое является строкой '', но также имеет числовое значение 0.

my $review = $model->test ? 1 : !1;

Обратите внимание, что это можно упростить:

my $review = !! $model->test; # invert it twice

Если вы хотите изменить значение только тогда, когда оно ложно, вы можете использовать оператор или ||.

my $review = $model->test || !1;

Если вы действительно хотите узнать, определено ли это, или нет, почему бы вам просто не использовать defined.

my $review = defined $model->test;

Если вы хотите изменить значение только тогда, когда оно undefined, и у вас есть Perl 5.10 или новее, вы можете использовать определенный оператор или <(t213 > ).

my $review = $model->test // !1;

На более раннем Perl это потребует более одного statement.

my $review = $model->test;
$review = !1 unless defined $review;
2
ответ дан 20 авг. '13 в 4:39
источник