И снова говорю вам ЗДРАВСТВУЙТЕ! Если вы это читаете, значит продержались, к моей большой радости, до 9-го шага. Сегодня мы будем рассматривать достаточно трудные моменты языка. Если кому-то что-то будет непонятно (или было непонятно в предыдущих шагах), то пишите мне и я постраюсь объяснить. Если писем с "непонятками" на какой-то шаг наберётся определённое кол-во, то я буду переписывать этот шаг в более понятной форме. Поехали (запил кофеём)!
В Perl нет разделения на процедуры и функции, поэтому мы будем использовать общее определение - "подпрограмма". Мы научимся в этом шаге создавать свои подпрограммы, рассмотрим некоторые тонкости вызова встроеных функций Perl, коснёмся вопроса "Что такое указатель и зачем он нужен немерянно крутому программеру, которым я хочу стать?" и узнаем о пользе рукурсии в деле программерском.
Для применения подпрограммы ее необходимо определить либо в текущем модуле (файле), либо во внешнем модуле (файле). Объявляются подпрограммы с помощью ключевого слова sub. Чтобы использовать подпрограмму объявленную во внешнем модуле, нужно перед её использованием указать интерпретатору где её искать следющим образом use имя_модуля qw(подрограмма) или require имя_файла. Как происходит вызов подпрограмм посмотрим на примере
#!/usr/bin/perl -w sub test { print "Привет из подпрограммы!\n"; } &test();
Cимвол & означает, что после него идёт вызов подпрограммы. Т.е. в данном случаем вызов подпрограммы test(). Но можно даже обойтись вообще без него. Теперь ещё одна тонкость. Обойтись можно и без скобок. Выглядеть это будет так:
#!/usr/bin/perl -w sub test { print "Привет из подпрограммы!\n"; } test;
Причем обойтись без скобок можно не только в тех подпрограммах, которые создаём мы, но и при вызове функций Perl. Скобки нужны только в том случае, если передаваемые функции параметры могут вызвать неоднозначность трактования. Мы уже не раз "своевольничали", не пользуясь скобками. Функция print правильно пишется так - print("Привет из подпрограммы!\n"). Теперь о том, как передаются подпрограммам параметры. Каждая подпрограмма при запуске получает массив @_, в котором содержатся параметры. Ещё один пример:
#!/usr/bin/perl -w sub test { print $_[0]; } &test("Привет из подпрограммы!\n");
...или так:
#!/usr/bin/perl -w sub test { print $_[0]; } test "Привет из подпрограммы!\n";
Ощутили? Поехали дальше :) Подпрограммы могут быть объявленны как перед их вызовом, так и после. Подпрограммы могут возвращать какое-то значение. Для этого служит оператор return, он возвращает идущее за ним значение.
#!/usr/bin/perl -w sub test { return "Я вернулся :)"; } print &test();
Можно обходится и без него. Тогда Perl вернёт значение последнего оцененного выражения. Ещё о передаче подпрограмме параметров. В Perl все переменные передаются по ссылке. Поэтому нет смысла передавать подпрограмме указатель на переменную. При передаче параметром массива, мы фактически передаём ту же ссылку на первый элемент массива, поэтому можно так же, как с переменной, не указывать специально, что мы передаём указатель. Но я всё же покажу как это делается. Указатель - это переменная содержащая адрес другой переменной. Чтобы объявить указатель надо перед переменной поставить символ *. Примерно так:
*POINTER;
Чаще всего указатели служат для хранения хэндлера. Что такое хэндлер мы скоро рассмотрим. Операция взятия адреса в Perl обозначается сиволом '\'. Небольшой пример:
#!/usr/bin/perl -w $x=0; print \$x;
Как видите мы получили не содержимое переменной, а её адрес - 0x18326bc (у вас может быть другой).
А сейчас рассмотрим как вынести свои подпрограммы в отдельный файл. Для этого достаточно сохранить свою подпрограмму в файл (предположим "test.pl"), а в том файле, в котором стоит вызов подпрограммы написать require "test.pl". Как делать модули мы узнаем позже.
Обещаная рекурсия. Рекурсивной называется подпрограмма, способная вызывать саму себя. Что это даёт? Например, возможность обработки древовидных структур, как то - дерево каталогов, ссылочная связь гипертекстовых документов и т.п. Ни с сетью, ни с файлами мы пока работать не умеем. Научимся чуть позже. Поэтому пока будем эмулировать бурную деятельность :)
#!/usr/bin/perl -w $cnt=0; sub recurs { my $level = $_[0]; $cnt++; print "$level\n"; if($cnt<10) { &recurs("$level\\$cnt"); } $cnt--; print "$level\n"; } &recurs(0);
Треугольничек :)