Именованные блоки
В Perl блок операторов, заключенный
в фигурные скобки, семантически эквивалентен циклу, выполняющемуся только
один раз. В связи с этим обстоятельством можно использовать команду last
для выхода из него, а команду redo для повторного вычисления операторов блока.
Команда next также осуществляет выход из блока, но отличается от команды last
тем, что вычисляются операторы блока continue, который может задаваться для
блока операторов в фигурных скобках:
BLOCK1: {
$i = 1;
last BLOCK1; } continue {
++$i; }
print "Переменная \$i после BLOCK1: $i\n"; BLOCK2: {
$i = 1;
next BLOCK2; } continue {
++$i; } print "Переменная \$i после BLOCK2: $i\n";
Первый оператор print этого фрагмента кода напечатает значение переменной $i
равным n, тогда как второй оператор print напечатает 2, так как при выходе
из блока BLOCK2 будет выполнен оператор увеличения на единицу переменной $i
из блока continue.
Замечание
Если в простом блоке операторов задан
блок continue, то при нормальном завершении простого блока (без использования
команд управления циклом) блок операторов continue также будет выполнен.
Блоки могут иметь метки, и в этом
случае их называют именованными блоками. Подобные конструкции используются
для реализации переключателей — конструкций, которые не определены в синтаксисе
языка Perl. Существует множество способов создания переключателей средствами
языка Perl. Один из них представлен в примере 5.18.
#! peri -w $var = 3; SWITCH: {
$casel = 1, last SWITCH if $var == 1;
$case2 = 1, last SWITCH if $var == 2;
$case3 = 1, last SWITCH if $var = 3;
$nothing = 1; }
После выполнения именованного блока операторов SWITCH переменная $casei будет
равна 1, если $var равна i, $case2 будет равна 2, если $var равна 2 и, наконец,
$case3 будет равна 3, если $var равна 3. В случае, если переменная $var не равна
ни одному из перечисленных значений, то переменная $nothing будет равна i. Конечно,
это простейший переключатель, разработанный всего лишь для демонстрации возможности
быстрого создания переключателя в Perl. Для выполнения группы операторов в переключателе
можно использовать не модификатор if, а оператор выбора if.
Блоки могут вложенными друг в друга. Именованные блоки и команды управления
циклом, используемые для выхода из внутренних блоков, позволяют создавать достаточно
прозрачные конструкции, реализующие сложные алгоритмы. Например, можно организовать
бесконечный цикл без использования какого-либо оператора цикла:
$notempty = 0; $total = 0; INPUT: {
$line=<STDIN>; chop($line);
last INPUT if $line eq "END"; # Выход из бесконечного цикла ++$total;
redo INPUT if $line eq ""; ++$notempty; redo INPUT; }
Узнаете программу примера 5.16? Действительно, это реализация без оператора
цикла программы ввода строк и подсчета общего числа введенных, а также непустых
строк. Единственное, что нам пришлось добавить — еще одну команду redo в конце
блока операторов.