Операция «диапазон»

Бинарная «операция «диапазон» (..), по существу, представляет две различных операции в зависимости от контекста, в котором она используется.

Списковый контекст

В списковом контексте она возвращает список значений, зависящий от типа ее операндов. Если они представлены числовыми значениями, причем значение левого операнда меньше правого, то результатом ее выполнения является список, состоящий из последовательности увеличивающихся на единицу целых чисел. Список начинается со значения, определяемого левым операндом, и не превосходит числового значения, представленного правым операндом. Если значение какого-либо операнда не является целым, оно приводится к целому отбрасыванием дробной части числа.
Операция «диапазон» в списковом контексте чаще всего используется для задания значений элементов массивов и хэш-массивов и их фрагментов, а также она удобна для организации циклов for и foreach.
В качестве операндов операции «диапазон» могут выступать и скалярные переменные. При этом может оказаться, что значение левого операнда больше значения правого. В таком случае операция «диапазон» в списковом контексте возвращает пустой список. Если она использовалась для задания элементов массива, то массив оказывается неопределенным. Подобную ситуацию можно отследить с помощью функции defined() или простой проверкой количества его элементов. Рассмотрим случаи использования операции «диапазона» с числовыми значениями в списковом контексте.
Напечатает числа от -5 до 5, каждое на новой строке:
foreach $cycle (-5..5) {
  print "$cycle\n"; }
Напечатает строку "-5-4-3-2-1012345":
for(-5..5) {
  print; }
Использование переменных:
$min = 2;
$max = -2;
@аrrау = ($min .. $max);            # Массив не определен.
print "@array\n" if define(@array); # Печати не будет!
print "@array\n" if @array;         # Печати не будет!
Если операндами операции «диапазон», являются строковые данные, содержащие буквенно-цифровые символы, то в списковом контексте эта операция возвращает список строк, расположенных между строками, являющимися значениями операндов, в соответствии с лексикографическим порядком:
@а = ("а".."d" );    # @а: "а", "b", "с", "d"
@а = ("01".."31" );  # @а: "01", "02", ... , "30", "31"
@а = ("а1".."b2" );  # @а: "a1", "a2", "аЗ", "а4", "а5",
                     # "а6", "а7", "а8", "а9", "b0"
                     # "b1", "b2"
Если с точки зрения лексикографического порядка левый операнд меньше правого, то возвращается единственное значение, равное значению левого операнда.
ПРИМЕЧАНИЕ. Операция «диапазон» не работает со строками, содержащими символы национальных алфавитов. В этом случае она всегда возвращает единственное значение, соответствующее левому операнду.

Скалярный контекст

В скалярном контексте операция «диапазон» возвращает булево значение «истина» или «ложь». Она обладает двумя устойчивыми состояниями, как триггер, и эмулирует операцию «запятая» (,) пакетного редактора sed и фильтра awk операционной системы UNIX, представляющую диапазон обрабатываемых этими программами строк.
Каждая операция «диапазон» в скалярном контексте поддерживает свое собственное булево состояние, которое изменяется в процессе ее повторных вычислений по приведенной ниже схеме.
Она находится в состоянии «ложь», пока ложным остается значение ее левого операнда.
Как только значение левого операнда становится «истина», операция «диапазон» переходит в состояние «истина» и находится в нем, пока значение ее правого операнда остается ложным. Как только оно станет равным «истина», операция снова переходит в состояние «ложь».
Правый операнд не вычисляется, пока операция находится в состоянии «ложь»; левый операнд не вычисляется, пока операция «диапазон» находится в состоянии «истина».
В состоянии «ложь» возвращаемым значением операции «диапазон» является пустая строка "", которая трактуется как булево значение «ложь». В состоянии «истина» при повторном вычислении она возвращает следующее порядковое число, отсчет которого начинается с единицы. Таким образом, как только операция переходит в состояние «истина», она возвращает 1, при последующем вычислении, если она все еще находится в состоянии «истина», возвращается 2 и т. д. В момент, когда операция переходит в состояние «ложь», к ее последнему возвращаемому порядковому числу добавляется строка символов Е0, которая не влияет на возвращаемое значение, но может быть использована для идентификации последнего элемента в диапазоне вычислений.
Достаточно полезное свойство операции «диапазон» в скалярном контексте, используемое при обработке текстовых файлов, заключается в том, что если какой-либо операнд этой операции задан в виде числового литерала, то он сравнивается с номером прочитанной строки файла, хранящейся в специальной переменной $., возвращая булево значение «истина» при совпадении и «ложь» в противном случае. В программе из листинга 4.2 иллюстрируется такое использование операции «диапазон».
Очень часто заголовочная часть файла отделяется от его смыслового содержимого пустой строкой, например, при выполнении браузером POST-запроса к серверу в соответствии со спецификацией HTTP строка запроса и заголовки запроса отделены пустой строкой от пересылаемых в теле запроса данных. Предположим, что у нас есть файл именно с такой структурой: его заголовочная часть отделена пустой строкой от его содержимого. Наша задача — обработать только содержимое файла. Программа из листинга 4.2 осуществляет пропуск первых непустых строк файла и отображает на экране монитора его смысловое содержимое, непосредственно следующее после пустой строки заголовочной части.
Листинг 4.2. Операция «диапазон» в обработке строк файла
#! perl -w
open(FILE, "file.txt") or die "He открыть файл file.txt!";
while(<FILE>) {
  $temp = 1../^$/; # «истина», пока строка файла непустая.
  next if ($temp); # Переход на чтение новой строки.
                   # если $temp истинна, 
  print $_;        # Печать первой строки файла после непустой
}
close(FILE);
В этой программе для нас интересен оператор присваивания возвращаемого значения операции «диапазон» переменной $temp. Прежде всего, отметим, что эта операция используется в скалярном контексте, причем ее левый операнд представлен числовым литералом. На первом шаге цикла читается первая строка файла и специальной переменной $. присваивается ее номер 1, который сравнивается со значением левого операнда операции «диапазон». Результатом этого сравнения является булево значение «истина» и операция «диапазон» переходит в состояние «истина», в котором она и остается, если первая строка файла непустая, так как операция поиска по образцу /^$/ возвращает в этом случае «ложь». Операция next осуществляет переход к следующей итерации цикла, во время которой читается вторая строка файла. Операция «диапазон» остается в состоянии «истина», если прочитанная строка файла пустая (правый операнд остается ложным), увеличивая возвращаемое значение на единицу. Далее операция next снова инициирует чтение новой строки файла. Если строка файла пустая, то операция поиска по образцу возвращает значение «истина», переводя тем самым операцию «диапазон» в состояние «ложь», которое распознается при следующем ее вычислении, поэтому считывается еще одна строка файла (первая после пустой). Теперь операция next не выполняется, так как операция «диапазон» возвращает «ложь», и печатается первая непустая строка. При чтении последующих строк файла операция «диапазон» возвращает «ложь» и таким образом мы получаем распечатку смыслового содержимого файла.

Следующая страница Содержание главы


Реклама