2012-01-19 4 views
22

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

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

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

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

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

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

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

+0

Вы действительно должны установить его в '1' не ' «» '. Оба они имеют одинаковое строковое представление ('' ''). Единственное различие заключается в том, что '' '' будет предупреждать, если вы попытаетесь использовать его как число, где как '! 1' не будет. (Предполагая, что у вас всегда есть 'использование предупреждений,' в верхней части каждого фрагмента кода Perl, как вы должны.) –

ответ

32

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

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

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

+0

Спасибо, Грег! Мне даже кажется странным, что я даже спрашиваю, потому что кажется, что все будет так просто. (и это!) JW –

+0

@JaneWilkie На самом деле, это проще, чем это. См. Мой ответ. – tchrist

+0

Конечно, лучший ответ WAY заключался бы в том, чтобы изменить определение MySQL на CHAR (1) вместо BIT (1), но, к сожалению, политика изменения чего-то такого простого в нашей производственной среде огромна. –

9

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

Тогда просто использовать это:

$review = $model->test || ""; 
+0

Tom и Foy в той же теме. Где Ларри Уолл? Я хочу, чтобы все мы выстроились в линию, чтобы я мог сфотографироваться с вами, ребята. – Alhadis

2

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

Но проблема с

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

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

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

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

$review = "1" = ''; 

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

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

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

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

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

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

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

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

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

НО:

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

$review = defined($model->test); 
+0

Что делать, если 'undef' является всего лишь ложным значением, и метод переписывается для возврата' '' 'или' 0' в качестве значения false? –

+0

@BradGilbert: Тогда я предполагаю, что вы не захотите применить к нему 'defined'. Очевидно, вам нужно знать, что возвращает метод, чтобы иметь возможность использовать его. –

+0

Это не значит, что test() должен предоставлять значения, подходящие для любого другого использования, и было бы плохой формой, чтобы полагаться на это. Такие вещи приводят к жесткой связи и жестким испытаниям. –

20

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

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

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

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

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

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

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

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

Но почему изменение UNDEF в пустую строку?

my $review = $model->test; 
1
my $result = defined $model->test ? '1' : ''; 
+0

Это устанавливает '$ result' почти такое же значение, как и' $ result = defined $ model-> test; '. Основное различие заключается в том, что ваш пользователь будет предупреждать, если он используется как число. –

2

Я предполагаю, что $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; 

Если вы хотите изменить значение только тогда, когда оно не определено, и у вас есть Perl 5.10 или более поздней версии, вы можете использовать defined-or operator (//).

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

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

my $review = $model->test; 
$review = !1 unless defined $review; 
7

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

my $review = do { 
    if(...) { 'foo' } 
    elsif(...) { 'bar' } 
    elsif(...) { 'baz' } 
    else   { 'defaut' } 
    }; 
+0

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

Смежные вопросы