Выбор значения по умолчанию

Проблема

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

Решение

Воспользуйтесь оператором || или ||=, работающим как со строками, так и с числами:
# Использовать $b, если значение $b истинно, и $с в противном случае
$а = $b || $с;
# Присвоить $х значение $у, но лишь в том случае,
# если $х не является истинной
$х ||= $у;
Если ваша переменная может принимать значения 0 или "0", воспользуйтесь функцией defined:
# Использовать $b, если значение $b определено, и $с в противном случае
$а = defined($b) ? $b : $с;

Комментарий

Главное отличие между этими двумя приемами (defined и ||) состоит, прежде всего, в том, что именно проверяется — определенность или истинность. В мире Perl три определенных значения являются ложными: 0, "0" и "". Если ваша переменная содержит одну из этих величин, но вы не хотите изменять ее, || не подойдет — приходится выполнять неуклюжие проверки с defined. Часто бывает удобно организовать программу так, чтобы принималась в расчет истинность или ложность переменных, а не их определенность.
В отличие от других языков, где возвращаемые значения ограничиваются 0 и 1, оператор || Perl обладает более интересным свойством: он возвращает первый (левый) операнд, если тот имеет истинное значение; в противном случае возвращается второй операнд. Оператор && ведет себя аналогично (для второго выражения), но этот факт используется реже. Для операторов несущественно, что представляют собой их операнды — строки, числа или ссылки; подойдет любое скалярное значение. Они просто возвращают первый операнд, из-за которого все выражение становится истинным или ложным. Возможно, это расходится с возвращаемым значением в смысле булевой алгебры, но такими операторами удобнее пользоваться.
Это позволяет установить значение по умолчанию для переменной, функции или более длинного выражения в том случае, если первый операнд не подходит. Ниже приведен пример использования ||, в котором $fоо присваивается либо $bаr, либо, если значение $bаr ложно, — строка "DEFAULT VALUE":
$foo = $bar || "DEFAULT VALUE"
В другом примере переменной $dir присваивается либо первый аргумент командной строки программы, либо "/tmp", если аргумент не указан:
$dir = shift(@ARGV) || "tmp"
То же самое можно сделать и без изменения @ARGV:
$dir = $ARGV[0] || "/tmp"
Если 0 является допустимым значением $ARGV[0], использовать потому что вполне нормальное значение будет интерпретировано как ложное. Приходится обращаться к тернарному оператору выбора:
$dir = defined($ARGV[0]) ? shift(@ARGV) : "/tmp";
To же можно записать и иначе, со слегка измененной семантикой:
$dir = @ARGV ? $ARGV[0] : "/tmp"
Мы проверяем количество элементов в @ARGV. В условии оператора выбора (?:) @ARGV интерпретируется в скалярном контексте. Значение будет ложным лишь при нулевом количестве элементов, в этом случае будет использоваться "/tmp". Во всех остальных ситуациях переменной (когда пользователь вводит аргумент) будет присвоен первый аргумент командной строки.
Следующая строка увеличивает значение %count, при этом в качестве ключа используется значение $shell, а если оно ложно — строка "/bin/sh".
$count{$shell || "/bin/sh"}++;
В одном условии можно объединить несколько альтернативных вариантов, как показывает следующий пример. Результат совпадает с первым операндом, имеющим истинное значение.
# Определить имя пользователя в системе UNIX
$user = $ENV{USER}
||  $ENV{LOGNAME}
||  getlogin()
||  (getwuid($<))[0]
||  "Unknown uid number $<";
Оператор && работает аналогично; он возвращает первый операнд, если этот операнд ложен. В противном случае возвращается второй операнд. Поскольку ложные значения представляют интерес существенно реже, чем истинные, это свойство используется не так часто.
Оператор присваивания || = выглядит странно, но работает точно так же, как и остальные операторы присваивания. Практически для всех бинарных операторов Perl $VAR ОР = VALUE означает $VAR = $VAR OP VALUE; например, $а += $b – тоже, что и $а = $а + $b. Следовательно, оператор ||= может использоваться для присваивания альтернативного значения переменной. Поскольку || выполняет простую логическую проверку (истина или ложь), него не бывает проблем с неопределенными значениями, даже при использовании ключа -w.
В следующем примере = присваивает переменной $starting_point значение "Greenwich", если оно не было задано ранее. Предполагается, что $starting_point не принимает значений 0 или "0", а если принимает — то такие значения должны быть заменены:
$starting_point  ||= "Greenwich"
В операторах присваивания || нельзя заменять оператором or, поскольку or имеет слишком низкий приоритет. Выражение $а = $b or $с эквивалентно ($а = $b) or $c. В этом случае переменной $Ь всегда присваивается $а, а это совсем не то, чего вы добивались.
Не пытайтесь распространить это любопытное применение || и || = со скалярных величин на массивы и хэши. У вас ничего не выйдет, потому что левый операнд интерпретируется в скалярном контексте. Приходится делать что-нибудь подобное:
@а = @b unless @a;  # Копировать, если массив пуст
@а = @>b ? @b : @с; # Присвоить @Ь, если он не пуст, иначе @с

См. также

Описание функций defined и exists



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: