15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


ЦИКЛЫ И ВЕТВЛЕНИЯ

Perl поддерживает операторы циклов for, while и do с не-
большими отличиями от их реализации в языке С. Существенным отли-
чием служит то, что Perl требует использования инструкций блока-
ми, заключенными в фигурные скобки. Кроме того, как вы познакоми-
тесь , далее, Perl расширяет конструкцию цикла, что6ы обеспечить
ее некоторые новые формы. В следующих примерах циклы for, while и
do работают аналогичным образом на языках С и Perl:

for($i = 0; $i< 100;$i++)
{
printf("%d\n", $i) ;
}
while ($i > 0)
{
printf("%d\n", $i-);
}
do {
printf("%d\n", $i++);
} while ($i < 0);

Конструкция циклов на языке С отлична от конструкции на язы-
ке Perl еще и в том, что Perl не содержит оператора break, а опе-
ратор continue выполняет совершенно иную функцию. К счастью, Perl
обеспечивает некоторые новые, более гибкие и более интуитивно по-
нятные конструкции:

? last выход из цикла (как оператор С break)
? next начать новую итерацию (как оператор С continue)
? redo повторить текущую итерацию

Для понимания конструкций циклов на языке Perl, необходимо
разобраться с использованием блока continue. Рассмотрим следую-
щий цикл while, который содержит блок continue:
$i = 100;
while ($i > 0)
{
print $i;
} continue {$i-}

Вы можете представлять себе блок continue как третье выраже-
ние в цикле for, которое выполняется на каждой итерации. Анало-
гичным образом Perl выполняет блок continue в конце каждой итера-
ции. Однако, как вы узнаете далее, блок continue обеспечивает
скрипту более полный контроль над процессом, чем обеспечивает
цикл for. Когда цикл на языке Perl использует оператор next, блок
continue все равно выполняется, если только он существует. Одна-
ко если цикл использует оператор redo, блок continue не испол-
няется.

МЕТКИ
В скрипте Perl метки просто означают имя, соответствующее
некоему положению внутри скрипта. Имена меток оканчиваются двое-
точием (например, outerloop:). Используя оператор goto, скрипт
может осуществлять переходы на метку. Дополнительно могут ис-
пользоваться операторы last, next и redo, для перехода к метке.
Следующий код иллюстрирует использование оператора last для пере-
хода на метку:

outerloop: while ($i > 0)
{
while ($j > 0)
{
#Здесь какой-нибудь другой процесс

if ($needToAboutLoop)
{
last outerloop;
}
}
}

В этом случае инструкция содержит ветвь last для перехода на
метку outerloop и окончания выполнения цикла.

ЦИКЛ UNTIL
Еще одной конструкцией цикла в языке Perl является цикл
until, который является противоположностью циклу while. Как вы
помните, в цикле while инструкции выполняются до тех пор, пока
выполняется заданное условие. В цикле until, напротив, инструк-
ции выполняются до тех пор, пока не будет выполнено условие. Нап-
ример, рассмотрим цикл while, такой, как показан на следующей
странице.

while (!(expr))
{
statement;
}
Используя цикл until, можно создать идентичный цикл, пока-
занный ниже:

until (expr)
{
statement;
}

Аналогичным образом следующая конструкция do while ис-
пользует оператор логического отрицания для того, чтобы выпол-
нять цикл, пока заданное булево выражение не станет истинным:

do {
statement;
} while (!(expr));

Используя конструкцию do until, вы можете сформировать иден-
тичный цикл без использования логического отрицания:

do
{
statement;
} until (expr);

ЦИКЛЫ FOR И FOREACH
Perl поддерживает цикл for совершенно аналогично языку С:

for (statement1; expression; statement2)
{
statement3;
}

Например, следующий код использует цикл for для того, чтобы
вывести значения чисел от 0 до 100:

for ($digit = 0; $digit <=100; $digit++)
{
print $digit, ' ';
}

Дополнительно Perl содержит конструкцию цикла foreach, кото-
рый позволяет скрипту организовывать итерации в списках и масси-
вах. Рассмотрим пример:

@list = ('a','b','c');

foreach $arg (@list)
{
print "List item: $arg\n";
}

foreach $i (1..10)
{
print "iteration $i\n"
}

В первом случае цикл foreach осуществлял перебор значений в
списочной переменной @list. Во втором примере в цикле foreach
осуществляется перебор чисел в диапазоне от 1 до 10.
Внутри цикла foreach может фигурировать список, состоящий из
литералов, или массив, как было проиллюстрировано в предыдущем
примере. После выполнения одной итерации циклом, специальная ска-
лярная переменная {$arg в первом случае и $i во втором случае)
принимает значение из заданного списка элементов. Область види-
мости этой скалярной переменной в цикле foreach ограничивается
телом цикла. Поэтому скалярная переменная цикла, foreach не бу-
дет конфликтовать с идентичным именем переменной, определенной
вне цикла. В следующем коде переменная с именем $i используется
внутри и вне цикла foreach:

$i = 1001;
foreach $i (1..9)
{
print "$i\n"; # цикл выведет 123456789
}

print "$i\n";

Как можно увидеть из этого примера, переменная $i, ис-
пользуемая для организации итераций цикла, не конфликтует с пере-
менной $i, определенной вне цикла.
Особенностью цикла, foreach, которую ваши скрипты могут ис-
пользовать, является возможность модификации элементов массива.
(Будьте осторожны при реализации этой возможности!) Рассмотрим
следующий цикл foreach, который добавляет значение 10 каждому
элементу массива:

@list = 1..5;
foreach $i (@list)
{
$i += 10;
}

$, = ' ';
print @list; # выведет 11 12 13 14 15

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

ОПЕРАТОР БЕЗУСЛОВНОГО ПЕРЕХОДА GOTO
Perl поддерживает оператор безусловного перехода goto, кото-
рый является идентичным такому же оператору языка программирова-
ния С. Ниже приведен пример использования оператора goto для вы-
вода чисел от 1 до 10:

$i = 1;
loop:
print $i++, ' ';

if ($i <=10)
{
goto loop;
}

МОДИФИКАТОРЫ ОПЕРАТОРОВ
В языке Perl используются специальные формы конструкции if,
unless, while и until, которые позволяют управлять ходом вычисле-
ний. В определенных случаях эти cпециальные конструкции могут
сделать ваш код более ясным и легко читаемым. Для того, чтобы код
было легче читать и его смысл был более очевиден, целесообразно
выбирать подходящий формат для записи. Рассмотрим следящее выра-
жение, использующее функцию die для того, чтобы закончить выпол-
нение скрипта, если значение переменной $count меньше чем 10:

if ($count < 10)
{
die;
}

Если расположить функцию die перед оператором if, как пока-
зано ниже, число строк кода уменьшится:

die if ($count < 10);

Аналогичным образом, то же самое выражение может быть запи-
сано в следующем виде:

($count >= 10) || die;

В данном случае, если переменная $count больше либо равна
10, Perl прекращает дальнейшее вычисление в данной строке и фун-
кция die не выполняется В противном случае, если переменная
$count меньше 10, после вычисления первой части выражения код за-
пускает функцию die и тем самым заканчивает выполнение скрипта.
Наконец, в следующем примере использование конструкции
unless также позволяет уменьшить число строк до одной:

die unless ($count >= 10);

Аналогичным образом, следующие циклы while являются идентич-
ными:

$i = 0;
while ($i < 10)
{
$i++;
}

$i = 0;
$i++ while ($i < 10);

Как можно видеть, используя модификацию конструкции, скрипт
позволяет сократить число строк в записи цикла до одной. Анало-
гичным образом, следующие циклы until эквивалентны:

$i = 10;
until ($i >= 10)
{
$i++;
};

$i = 10;
$i++ until ($i >=10);

Примечание: Во всех четырех случаях, даже если выражение для оце-
нивания расположено после инструкции для выполнения, Perl снача-
ла анализирует условие и только потом выполняет инструкцию.

ГЕНЕРАЦИЯ ДИНАМИЧЕСКИХ ВЫРАЖЕНИЙ С ПОМОЩЬЮ ФУНКЦИИ EVAL
Поскольку Perl является интерпретируемым языком, ваши скрип-
ты могут использовать Perl для того, чтобы генерировать код <на
лету>, то есть динамически, во время исполнения скрипта. Именно
так работает отладчик Perl (который сам является Perl-программой
с именем Perldb.PL). Проектируя скрипты, вы можете использовать
такой динамический код для создания динамических переменных имен
или даже построения специальных подпрограмм. Perl оценивает дина-
мические выражения, используя функцию eval. В следующем примере
создается динамическая инструкция путем присвоения переменной в
качестве значения текста, который, собственно, и содержит требуе-
мую инструкцию языка Perl. Дальнейшие инструкции используют фун-
кцию eval для того, чтобы выполнить эту инструкцию:

$perl_statement = 'print "Hello, world\n";';

eval $perl_statement; # выведет Hello, world
$i = 1001;
$varname = '$i';
print eval $varname; # выведет значение $i

Примечание: Использование скриптом функции eval таит в себе опас-
ности, в особенности, если скрипт передает функции eval данные,
полученные от пользователя. Используя функцию eval, скрипт может
выполнить произвольную команду языка Perl, включая даже систем-
ные команды. Это дает возможность пользователю контролировать
программу, что может быть особенно рискованным для сетей Internet
и Web.

ПОДПРОГРАММЫ
Как и все структурированные языки программирования, Perl
поддерживает подпрограммы. Подпрограмма может быть определена с
помощью ключевого слова sub, как показано ниже:

sub demo_sub
{
print "demo_sub called\n";
}

&demo_sub; # вызов подпрограммы

В данном случае инструкции образуют подпрограмму, названную
demo_sub. Для вызова подпрограммы скрипт помещает знак амперсан-
да (&) перед именем подпрограммы. При вызове подпрограммы в язы-
ке Perl скобки могут быть опущены.
Вы можете разместить подпрограмму где угодно в пределах ис-
ходного кода скрипта, потому что Perl проанализирует весь исход-
ный текст перед тем, как начать выполнение скрипта. Можно объя-
вить подпрограмму в исходном коде сразу после первого использова-
ния подпрограммы (forward reference). Подпрограммы могут иметь
аргументы и возвращать значения. Следующий фрагмент кода содер-
жит подпрограмму с именем show_value, которая выводит значение,
полученное подпрограммой в качестве параметра:

sub show_value
{
print 'The value id ', $_[0];
}

&show_value(1001);

Формально подпрограмма языка Perl не объявляет переменных
для хранения аргументов. Вместо этого в подпрограмму передается
переменная типа массив с именем @_, которая содержит значения па-
раметров. В свою очередь, подпрограмма получает доступ к значе-
ниям аргументов, используя следующие обозначения для элементов
массива: $_[0], $_[1], и т. д. Однако такой способ передачи пара-
метров может ухудшать читаемость кода, и поэтому большинство под-
программ используют копирование аргументов в локальные перемен-
ные. Аналогично предыдущему примеру, следующая подпрограмма
show_fwo_values выводит значения двух параметров:

sub show_two_values
{
print 'Первый параметр ', $_[0], "\n";
print 'Второй параметр ', $_[0], "\n";
}

&show_two_values(1001, 2002);

Наконец, следующая функция show_all_values выводит значения
всех параметров, которые она получает. Функция использует массив
для определения числа параметром:

sub show_all_values
{
for ($i = 0; $i < @_; $i++)
{
print 'Parametr ', $i, ' is ', $_[$i], "\n";
}
}

& show_all_values(1001,2002,3003,4004);

Как было сказано, подпрограммы Perl могут возвращать значе-
ния. Для этого используется инструкция return. В противополож-
ность языку С, Perl не требует обязательного использования ин-
струкции return. Если подпрограмма не содержит инструкцию return,
то в качестве возвращаемого значения будет взято последнее оце-
ненное выражение. В следующем примере складываются два параметра
и возвращается результат:

sub add_values
{
return $_[0] + $_[1];
}

print 'The result is: ', &add_values(1001,2002);

БИБЛИОТЕКА ПОДПРОГРАММ
В противоположность языку С, Perl фактически не поддержи-
вает концепцию библиотеки. Тем не менее, в нем имеется механизм,
позволяющий скриптам использовать исходный код из другого файла.
Например, предположим, что вы храните подпрограмму add_valuesl в
файле под именем addvalue.pl. Используя инструкцию require, дру-
гой скрипт на языке Perl может получить доступ к той подпрограм-
ме, как показано ниже:

require "addvalue.pl";
print &add_values(10,11);

Вы можете представлять себе инструкцию require как аналог
оператора #include препроцессора языка С. Чтобы найти файл исход-
ных кодов, Perl сначала ищет в каталоге, определенном по умолча-
нию для библиотеки языка Perl (подробности можно уточнить в ин-
струкции по инсталляции), а затем в текущем каталоге. Можно так-
же использовать абсолютный или относительный путь, к которому до-
бавлено имя файла.
Perl запоминает, какие файлы были затребованы оператором
require, и загружает их только один раз даже в случае многочис-
ленных обращений к этим файлам. Имеется много стандартных библио-
тек, которые расширяют возможности языка Perl. Сейчас самое вре-
мя побродить по каталогу, в котором хранятся библиотечные файлы
языка Perl, чтобы получить представление о тех возможностях, ко-
торые они предлагают.

Назад | Далее