Каждый простой оператор может быть снабжен модификатором,
представляющим ключевое СЛОВО 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( ! ВЫРАЖЕНИЕ-УСЛОВИЕ) { ВЫРАЖЕНИЕ; }
Замечание
ВЫРАЖЕНИЕ-УСЛОВИЕ вычисляется в булевом контексте: оно трактуется
как Ложь, если равно о или пустой строке " ", и
Истина — в любом другом случае.
Использование модификаторов if и unless показано в примере
5.1 — простой программе решения квадратного уравнения.
# 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
|