Операторы цикла
Цикл foreach
Одно из наиболее частых применений циклов в языках программирования – организация вычислений с элементами массивов: найти максимальный элемент, распечатать элементы массива, выяснить, существует ли элемент массива, равный заданному значению, и т. п. Подобные задачи легко решаются с помощью циклов while и for. В примере 5.9 определяется максимальный элемент массива (в предположении, что он содержит числовые данные).
#! peri – w @array = (1,-6.9.18.0,-10); $max = $array[0];, for ($i = 1; $i <= $farray; $i++) { $max = $array[$i] if $array[$i] > $max; }
После выполнения программы примера 5.9 переменная $max будет иметь значение 18, равное максимальному элементу массива $аггау. Обратим внимание читателя на то, что в цикле for (как и в цикле while) доступ к элементам массива организуется с помощью индекса.
В Perl списки и массивы, являющиеся, по существу, также списками, являются столь полезными и часто используемыми конструкциями, что для организации цикла по их элементам в языке предусмотрен специальный оператор foreach, имеющий следующий синтаксис:
МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК continue БЛОК
Он реализует цикл по элементам списка список, присваивая на каждом шаге цикла переменной ПЕРЕМЕННАЯ значение выбранного элемента списка. Блок операторов continue выполняется всякий раз, как начинается очередная итерация, за исключением первой итерации, когда переменная $temp равна первому элементу списка. Список можно задавать или последовательностью значений, разделенных запятыми, или массивом скаляров, или функцией, возвращаемым значением которой является список. Определение максимального элемента массива можно переписать с циклом foreach (пример 5.10).
#! peri, – w Sarray = (1,-6.9.18.0,-10); $max = $array[0]; foreach $temp (Sarray) ( $max = $temp if $temp > $max; } print "$max";
На каждом шаге цикла переменная $temp последовательно принимает значения элементов массива $аггау. Обратите внимание на внешний вид программы – в отсутствии индексов массива она стала лучше читаемой.
Отметим несколько особенностей цикла foreach. Прежде всего следует сказать, что ключевое слово foreach является синонимом ключевого слова for. Цикл из примера 5.10 можно было бы записать и так:
for $temp (@array) { # Ключевое слово foreach синоним for. $max = $temp if $temp > $max; }
Однако, как нам кажется, использование foreach лучше отражает семантику этого оператора цикла, так как в самом ключевом слове уже отражена его сущность (for each – для каждого).
Следующая особенность оператора foreach связана с переменной цикла. По умолчанию эта переменная является локальной, область видимости которой ограничена телом цикла. Она создается только на время выполнения оператора foreach, доступна внутри тела цикла и уничтожается при выходе из цикла.
Обычно программисты, работающие на языке Perl, вообще не применяют в циклах foreach переменную цикла. Это связано с тем обстоятельством, что в отсутствии явно заданной переменной цикла Perl по умолчанию использует специальную переменную $_. На каждом шаге цикла именно она будет содержать значение элемента списка или массива. С учетом этого факта цикл foreach примера 5.10 можно переписать так:
foreach (@array) { # В качестве переменной цикла используется $_. $гоах = $_ if $_ > $max; } .l
Последняя особенность оператора foreach, которая также связана с переменной цикла, заключается в том, что фактически на каждом шаге выполнения цикла эта переменная является синонимом того элемента списка, значение которого она содержит. Это означает, что ее изменение в цикле приводит к изменению значения соответствующего элемента списка. Это свойство цикла foreach удобно для изменения значений элементов списка. Отметим, что его можно применять к спискам, хранящимся в массивах. Например, возвести в квадрат каждый элемент списка можно следующим оператором foreach:
foreach $temp (@array) { $temp **= 2; }
Список, по элементам которого организуется цикл, может быть задан не только явно конструктором или переменной массива, но и функцией, возвращаемым значением которой является список. Канонический способ печати хеш-массива в упорядоченном порядке представлен в примере 5.11.
# peri – w %array = { blue › 1, red › 2, green › 3, yellow › 3); foreach (sort keys %array) { print "$_\t › $array{$_}\n"; } '
Эта программа напечатает пары ключ/значение хеш-массива %аггау в соответствии с алфавитным порядком его ключей:
blue › 1 green › 3 red › 2 yellow › 3
Замечание
Цикл foreach выполняется быстрее аналогичного цикла for, так как не требует дополнительных затрат на вычисление индекса элемента списка.