Блоки и составные операторы

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

Понятие блока и локальных переменных

В документации Perl блоком называется последовательность операторов, которая определяет область видимости переменных, определенных внутри блока и называемых локальными. Блок может быть ограничен последовательностью операторов из некоторого файла (например, внедряемый в программу с помощью функции do внешний файл или файл самой программы), а может быть ограничен какой-либо строкой, как в случае выполнения функции eval( ). Но чаше всего блок в программе ограничен фигурными скобками {...}. Определяя синтаксис составных операторов, мы будем иметь в виду именно такой блок — последовательность операторов в фигурных скобках — и обозначать его БЛОК.
Интерпретатор рассматривает БЛОК как один оператор, вычисляемым значением которого является значение последнего выполненного оператора блока. Это означает, что там, где можно использовать один оператор, можно использовать и БЛОК. Такая ситуация встречается при использовании функции map( ), которая вычисляет определяемое ее первым параметром выражение для всех элементов списка, заданного вторым параметром. Значение каждого элемента списка при вычислениях временно присваивается специальной переменной $_. Возвращает эта функция список вычисленных значений операции:
@rez = map $_ * $_, @array; # Массив @rez содержит квадраты
                            # элементов массива @аrrау
Как и в случае с модификатором foreach, переменная $_ не просто хранит последовательные значения элементов списка, а является их псевдонимом. Поэтому изменение ее значения приводит к изменению значения соответствующего элемента списка. Следующий оператор изменит значения всех элементов массива @аrrау на их квадраты:
mар $_ **= 2, @аrrау; # Элементы массива @аrrау
                      # возведены в квадрат
Первым параметром функции map( ) может быть и БЛОК, но синтаксис вызова функции в этом случае не предусматривает запятой между ее первым и вторым фактическими параметрами:
mар БЛОК СПИСОК;
Следующий вызов функции map( ) также заменяет элементы массива @аrrау на квадраты их значений, одновременно подсчитывая их первоначальную сумму и сумму их квадратов:
$kol1 = 0;
$kol2 = 0;
map { $kol1 += $_; $_ **= 2; $ko12 += $_ } @array;
При вычислении переменной $kol1 используется первоначальное значение соответствующего элемента массива @аггау, а при вычислении переменной $kol2 — уже измененное.
Обратите внимание, что возвращаемым значением блока операторов в этом примере является значение последнего оператора блока, которое и попадает в возвращаемый функцией map( ) список. В этом можно убедиться, если присвоить результат вычисления этой функции массиву скаляров и затем распечатать его значения. Мы увидим вычисление суммы квадратов значений элементов исходного массива @аrrау с нарастающим итогом.
В любом языке переменная обладает областью видимости (откуда можно на нее ссылаться) и временем жизни (как долго она существует). В данном разделе мы только наметим подходы к созданию переменных с ограниченной областью видимости, приводящие к так называемым лексическим и динамическим переменным.
Блок, как было сказано в начале этого раздела, определяет область видимости переменных. Это означает, что в нем можно создавать переменные, которые используются только в операторах этого блока. Пока мы в блоке, мы можем присваивать таким переменным новые значения, использовать их в вычислениях и т. п., но как только мы вышли из блока, мы теряем с ними «связь», они становятся «невидимыми», а проще говоря, уничтожаются. Такие переменные еще называют локальными переменными.
Локальные переменные создаются с помощью функции my( ). Ее параметром является заключенный в круглые скобки список переменных с областью видимости, ограниченной блоком, в котором они создаются. Если список состоит из одной переменной, то скобки не обязательны. Созданные функцией my( ) переменные называются также лексическими переменными, так как область их видимости (действия) определяется на этапе компиляции и ограничена фрагментом текста программы — блоком операторов.
В языке Perl можно создавать другой тип локальных переменных. Они создаются функцией lосаl( ) и называются локальными динамическими, так как их область действия определяется интерпретатором динамически во время выполнения программы. Однако именно переменные, созданные функцией my( ), являются «истинными» локальными переменными: они создаются при входе в блок и уничтожаются при выходе из него (хотя возможно определить режим, когда Perl сохраняет локальную лексическую переменную при выходе из блока), тогда как функция lосаl( ) всего лишь временно сохраняет старое значение некоторой глобальной переменной при входе в блок и восстанавливает его при выходе из блока. При этом внутри блока можно изменять значение локальной динамической переменной, правда, и доступно оно будет только внутри блока.
Локальные переменные удобны для создания временных переменных, которые не будут использоваться в программе нигде, кроме одного определенного места, синтаксически оформляемого как блок операторов. Следует отметить, что имена локальных переменных не конфликтуют с именами глобальных для данного блока переменных (то есть переменных, которые объявлены вне блока) и могут иметь такие же имена, как и глобально используемые переменные. После завершения выполнения операторов блока значение глобальной переменной, имя которой использовалось для создания временной локальной переменной, имеет то же значение, которое она имела до начала выполнения операторов блока.
ВНИМАНИЕ Если во внутреннем блоке мы объявим обычным способом переменную, не используя функции my( ) или lосаl( ), то такая переменная считается глобальной для веси программы и будет, естественно, видна в любом внешнем блоке.
Локальная переменная, вводимая функцией my( ), становится доступной только после выполнения соответствующего оператора ее объявления. Поэтому при создании локальной переменной с таким же именем, как и у глобальной переменной, возможна ее инициализация значением этой глобальной переменной:
my $var = $var;
Предполагается, что это объявление происходит в каком-либо блоке, для которого существует глобальная переменная $var.

Составные операторы

Составные операторы — это второй тип операторов языка Perl, которые используются для реализации ветвления и организации циклических вычислений в программе.
Операторы программы Perl выполняются последовательно в порядке их расположения в программе. Для реализации простых алгоритмов этого вполне достаточно. Однако большинство реальных алгоритмов не укладываются в такую линейную схему. Доказано (Э. Дейкстра), что любая структура управления, а следовательно, и реализуемые алгоритмы, могут быть функционально эквивалентно представлены суперпозицией трех простых структур управления, имеющих один вход и один выход: последовательного выполнения, ветвления по условию и цикла с предусловием. Именно последние две структуры управления и призваны реализовать составные операторы Perl.
Эти операторы, в отличие от аналогичных операторов других языков программирования, определяются в терминах блоков, с которыми мы только что познакомились. В языке определены следующие составные операторы:
if (ВЫРАЖЕНИЕ) БЛОК
if (ВЫРАЖЕНИЕ) БЛОК else БЛОК
if (ВЫРАЖЕНИЕ) БЛОК elsif (ВЫРАЖЕНИЕ) БЛОК ... else БЛОК
МЕТКА while (ВЫРАЖЕНИЕ) БЛОК
МЕТКА while (ВЫРАЖЕНИЕ) БЛОК continue БЛОК
МЕТКА for (ВЫРАЖЕНИЕ; ВЫРАЖЕНИЕ; ВЫРАЖЕНИЕ) БЛОК
МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК
МЕТКА foreach ПЕРЕМЕННАЯ (СПИСОК) БЛОК continue БЛОК
МЕТКА БЛОК continue БЛОК
ВНИМАНИЕ Напомним, что в составных операторах Perl под блоком БЛОК понимается последовательность операторов в фигурных скобках.
Первые три оператора реализуют ветвление в программе — вычисление последовательностей операторов соответствующих блоков в зависимости от истинности или ложности некоторого выражения. Остальные составные операторы представляют различные формы оператора цикла, организующего циклическое вычисление некоторой группы операторов.
Так как все составные операторы определяются в терминах блоков, то даже если в каком-либо из них по смыслу должны отсутствовать операторы, задание фигурных скобок { } обязательно.

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


Реклама