Управляющие конструкции с операторами неполного вычисления

Все четыре оператора, представленные в предыдущем разделе, &&, ||, // и ?:, обладают одной особенностью: вычисление выражения зависит от значения в левой части. Иногда выражение вычисляется, иногда нет. По этой причине они называются операторами неполного вычисления. Все операторы неполного вычисления автоматически являются управляющими конструкциями. Дело вовсе не в том, что Ларри горел желанием добавить в Perl побольше управляющих конструкций. Просто когда он решил включить эти операторы неполного вычисления, они автоматически стали управляющими конструкциями. В конце концов, все, что может привести к активизации и деактивизации фрагментов кода, по своей сути является управляющей конструкцией.

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

($m < $n) && ($m = $n);

Мы сразу видим, что результат логической операции AND ничему не присваивается. Почему? Если значение $m действительно меньше $n, левая сторона истинна, поэтому будет вычислена правая сторона с выполнением присваивания.


Но если переменная $m больше или равна $n, левая сторона будет ложной, а правая сторона игнорируется. Таким образом, эта строка кода фактически эквивалентна следующей, более понятной:

if ($m < $n) { $m = $n }

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

($m > 10) || print "why is it not greater?\n";

Если $m действительно больше 10, то левая сторона истинна и выполнение логического оператора OR завершено. В противном случае левая сторона ложна и программа переходит к выводу сообщения. Эту конструкцию тоже можно (и нужно) записать традиционным способом – вероятно, с if или unless. Как правило, подобная запись управляющих конструкций чаще всего применяется бывшими программистами C или программистами Perl старой школы. Почему? Одни ошибочно полагают, что она эффективнее. Другим кажется, что от этого их код смотрится «круче». Третьи просто копируют то, что они увидели где-то еще. Аналогичным образом тернарный оператор может использоваться для управления. В следующем примере $x присваивается меньшей из двух переменных:

($m < $n) ? ($m = $x) : ($n = $x);

Если $m меньше, $x присваивается ей, в противном случае $x присваивается переменной $n.


Существует еще одна разновидность записи логических операторов: их можно записывать словами and и or.1 Эти операторы ведут себя точно так же, как записываемые знаками, но «словарные» формы находятся в нижней части таблицы приоритетов. Так как слова не «прилипают» к ближним частям выражения, с ними иногда удается обойтись меньшим количеством круглых скобок:

$m < $n and $m = $n; # Но лучше записывать в эквивалентной форме if

А может оказаться и наоборот: понадобится больше круглых скобок. С приоритетами всякое бывает. Используйте круглые скобки, чтобы точно задать порядок выполнения операций, если вы не уверены в приоритетах. Но поскольку «словарные» формы обладают очень низким приоритетом, обычно бывает видно, что выражение делится на большие фрагменты. Сначала выполняется все, что находится слева, а затем (если понадобится) все, что находится справа. Хотя использование логических операторов в качестве управляющих конструкций запутывает программу, иногда они задействуются в стандартных идиомах. Общепринятый способ открытия файла в Perl выглядит так:

open CHAPTER, $filename
or die "Can't open '$filename': $!";

Используя низкоприоритетный оператор or с ускоренным вычислением, мы приказываем Perl: «Открой этот файл… или умри!» Если вызов open завершается успешно с возвращением истинного значения, выполнение or на этом заканчивается.


Но в случае неудачи ложное значение заставляет or вычислить правую часть, что приводит к аварийному завершению программы с выдачей сообщения. Таким образом, использование этих операторов в качестве управляющих структур является частью идиоматики Perl. Их правильное применение расширит возможности вашего кода, а неправильное затруднит его сопровождение. Не злоупотребляйте ими.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Автоинкремент и автодекремент
Значение автоинкремента
Значение ускоренного логического оператора
Логические операторы
Метки блоков