Каждый простой оператор может быть снабжен модификатором,
представляющим ключевое СЛОВО if, unless, while, until ИЛИ
foreach, за которым следует выражение-условие. В самом операторе
модификатор стоит непосредственно за выражением, составляющим
простой оператор, перед завершающим символом точка с запятой.
Каждый простой оператор может иметь только один модификатор.
Семантически роль модификатора сводится к тому, что оператор
вычисляется при выполнении условия, определяемого модификатором.
Например, следующий оператор присваивания
$n = $l/$m if $т != 0; с модификатором if будет выполнен при условии, что переменная $т не равна о. Общий синтаксис простого оператора с модификатором имеет следующий вид:
ВЫРАЖЕНИЕ ключ_слово_модификатора [(]ВЫРАЖЕНИЕ-УСЛОВИЕ [)];
Модификаторы if и unless
Модификаторы if
и unless употребляются в прямом смысле их английского значения.
Простой оператор с модификатором If выполняется, если ВЫРАЖЕНИЕ-УСЛОВИЕ
истинно. Семантически простой оператор
ВЫРАЖЕНИЕ if ВЫРАЖЕНИЕ-УСЛОВИЕ; эквивалентен следующему оператору условия:
if(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }
Замечание
В этом разделе мы представляем эквивалентные простым операторам с модификаторами соответствующие составные операторы языка Perl. Их синтаксис и применение будут детально разобраны в следующих параграфах, но мы уверены, что читатель поймет их и без дополнительных объяснений. Во всяком случае всегда можно вернуться к данному разделу, прочитав разделы, посвященные составным операторам языка Perl.
Модификатор unless
является прямой противоположностью модификатора if: простой
оператор выполняется, если ВЫРАЖЕНИЕ-УСЛОВИЕ не истинно. Общий
синтаксис простого оператора с модификатором unless имеет
следующий вид:
ВЫРАЖЕНИЕ unless ВЫРАЖЕНИЕ-УСЛОВИЕ;
Это всего лишь удобная форма записи оператора условия
if( ! ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }
Замечание
ВЫРАЖЕНИЕ-УСЛОВИЕ вычисляется в булевом контексте: оно трактуется как Ложь, если равно о или пустой строке " ", и Истина — в любом другом случае.
# peri -w
$а = <STDIN>;
$b = <STDIN>;
$с = <STDIN>;
$d = $b**2 - 4*$a*$c; # Вычисление дискриминанта уравнения
# Вычисление корней, если дискриминант положителен
( $xl =.(-$b+sqrt $d)/$a/2, $x2 = (-$b-sqrt $d)/$a/2 ) unless $d < 0;
# Печать результатов
print "Коэффициенты:\п а = $а b = $b с = $с"; print "\tPenieHHe:\n\t$xl\t$x2" if defined $xl; print "^Решения нет!" unless defined $xl;
Наша программа решения квадратного уравнения, конечно, примитивна. Из всех возможных проверок в ней проверяется на положительность только дискриминант квадратного уравнения, хотя стоило бы проверить на нуль значение вводимого пользователем с клавиатуры старшего коэффициента уравнения, сохраняемого в переменной $а.
Модификатор unless используется в операторах вычисления корней и печати сообщения об отсутствии решения. Обратите внимание, что в операторе печати проверяется, определена ли переменная $xi, а будет она определена только в случае положительности дискриминанта $d. В модификаторе if оператора печати корней уравнения также проверяется, определена ли переменная $xl.
Модификаторы while и until
Эти два модификатора
немного сложнее модификаторов if и unless. Они реализуют процесс
циклического вычисления простого оператора. Их синтаксис таков:
ВЫРАЖЕНИЕ while ВЫРАЖЕНИЕ-УСЛОВИЕ; ВЫРАЖЕНИЕ until ВЫРАЖЕНИЕ-УСЛОВИЕ;
Модификатор while повторно вычисляет ВЫРАЖЕНИЕ, пока истинно ВЫРАЖЕНИЕ-УСЛОВИЕ. Модификатор until противоположен модификатору while: ВЫРАЖЕНИЕ повторно вычисляется до момента, когда ВЫРАЖЕНИЕ-УСЛОВИЕ станет истинным, иными словами оно вычисляется, пока ВЫРАЖЕНИЕ-УСЛОВИЕ ложно.
Семантически эти модификаторы простых операторов эквивалентны следующим составным операторам цикла:
while(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; } until(ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }
Пример 5.2 дает представление о том, как работают модификаторы повтора while И until.
# peri -w $first = 10;
• $second = 10; $first++ while $first < 15; # $first увеличивается, пока не станет
# равной 15
—$second until $second < 5; # $second уменьшается, пока не станет
# равной 4
print "\$first $first\n"; print "\$second $second\n";
Оператор увеличения на единицу переменной $first будет выполняться, пока выражение $ first < 15 остается истинным. Когда значение переменной $first станет равным 15, выражение модификатора while становится ложным, и оператор завершает работу. Аналогично работает и следующий оператор уменьшения переменной $second на единицу. Единственное отличие от предыдущего оператора заключается в том, что он выполняется, пока выражение $ second < 5 модификатора until остается ложным. Два оператора печати выведут на экран значения переменных $first и $second равными соответственно 15 и 4.
Замечание
Модификаторы повтора следует применять к простым операторам, вычисление которых приводит к изменению условий модификаторов. Если это не так, то простой оператор либо вообще не будет выполнен, либо будет выполняться бесконечно. Например, следующий оператор
print $var while $var < 15; либо ни разу не напечатает значение переменной $var (если $var > =15), либо будет печатать бесконечно (если $var < 15). В последнем случае произойдет так называемое зацикливание и только нажатием комбинации клавиш <Ctrl>+<C> можно будет остановить выполнение этого оператора.
Модификаторы while
и until сначала проверяют истинность или ложность своих выражений-условий,
а потом, в зависимости от полученного результа, либо выполняют
простой оператор, либо нет. Таким образом, они реализуют цикл
с предусловием, при котором оператор, для которого они являются
модификаторами, может не выполниться ни одного раза.
Существует единственное исключение из этого правила, когда модификаторы повтора применяются к синтаксической конструкции do <}, которая не является оператором (хотя внешне и похожа), а относится к термам (см. главу 4). Поэтому, если ее завершить точкой с запятой, то такая конструкция будет являться простым оператором, к которому можно применять все возможные модификаторы Perl. Семантика этой конструкции заключается в том, что она вычисляет операторы, заданные в фигурных скобках {}, и возвращает значение последнего выполненного оператора. Так вот, если к простому оператору do {}; применить модификаторы повтора, то сначала выполнятся операторы конструкции do {}, а потом будет проверено условие модификатора. Это позволяет написать следующий простой оператор, который сначала осуществит ввод с клавиатуры, а потом проверит введенную информацию на совпадение с символом завершения ввода:
$string = ""; do{
$line = <STDIN>;
$string .= $line; I until $line eq ".\n";
Этот фрагмент кода будет накапливать вводимые пользователем строки в переменной $string до тех пор, пока не будет введена строка, состоящая из единственного символа точки, после чего оператор do{} until; завершит свою работу. Обратите внимание, что проверка в модификаторе until ведется на совпадение со строкой ". \п", в которой присутствует символ перехода на новую строку. Дело в том, что операция ввода <STDIN> передает этот символ в программу, так как пользователь именно этим символом завершает ввод строки (нажатие клавиши <Enter>).
Модификатор foreach
Модификатор foreach
ВЫРАЖЕНИЕ относится к модификаторам цикла. Он повторно выполняет
простой оператор, осуществляя итерации по списку значений,
заданному в ВЫРАЖЕНИЕ. На каждой итерации выбранный элемент
списка присваивается встроенной переменной $_, которую можно
использовать в простом операторе для получения значения выбранного
элемента списка. Например, следующий оператор распечатает
все элементы массива @т:
print "$_ " foreach @т; Общий синтаксис простого оператора с модификатором foreach следующий:
ВЫРАЖЕНИЕ foreach ВЫРАЖЕНИЕ-СПИСОК;
Простой оператор с модификатором foreach всего лишь удобная форма записи составного оператора jforeach:
foreach (ВЫРАЖЕНИЕ-СПИСОК) { ВЫРАЖЕНИЕ; }
Эта форма составного оператора foreach в качестве переменной цикла использует встроенную переменную $_ (см. раздел 5.4.3). Обратим внимание читателя на то, что ВЫРАЖЕНИЕ-список вычисляется в списковом контексте, поэтому все используемые в нем переменные ведут себя так, как они должны вести в списковом контексте. Например, хеш-массив представляет обычный список, составленный из последовательности его пар ключ/значение. Следующий фрагмент кода
%hash = ( one=>6, two=>8, three=>10 ); print "$_ " foreach %hash;
напечатает строку
three 10 two 8 one 6
Эта строка и есть тот простой список, который возвращает хеш в списковом контексте.
Относительно модификатора foreach (это же относится и к его эквивалентному оператору foreach) следует сказать одну важную вещь. Дело в том, что переменная $_ является не просто переменной, в которой хранится значение элемента списка текущей итерации, она является синонимом имени этого элемента. Это означает, что любое изменение переменной $_ в простом операторе приводит к изменению текущего элемента списка в цикле. Пример 5.3 демонстрирует, как просто можно умножить каждый элемент массива на некоторое число:
# peri -w
§array = (1, 2, 3);
$_ *= 2 foreach Sarray; # Умножение каждого элемента на 2.
print "@array"; # Напечатает строку: 246