Для применения подпрограммы ее необходимо определить либо в текщем модуле (файле) либо во внешнем модуле (файле). Подпрограммы определяются и декларируются следующим образом:
sub имя; # Только декларация. Определение ниже. sub имя (прототипы); # То же но с декларацией параметров. sub имя блок; # Декларация и определение. sub имя (прототипы) блок; # То же, но с парамметрами.
Для определения динамичской анонимной подпрограммы можно указать:
$переменная = sub блок;
Для импортирования подпрограмм из других модулей используйте:
use модуль qw(подпрограмма1 подпрограмма2);
Вызов подпрограммы:
имя(список параметров); # символ '&' можно не указывать. имя список; # Если подпрогрмма уже декларирована. &имя; # Параметры в @_
Все параметры передаются подпрограмме как массив @_. Соответсвенно $_[0] - первый параметр, $_[1] - второй и т.д. Массив @_ - локальный, но он содержит адреса параметров, поэтому можно изменять значение параметров.
Возвращаемое значение подпрограммы - результат последнего оператора. Это может быть как скаляр так и массив. Можно принудительно возвращать результат используя функцию return().
Подпрограмму можно вызвать используя префикс '&' перед именем подпрограммы. Если подпрограмма предварительно продекларирована, то префикс и скобки можно опустить.
Для применения переменных доступных только внутри блока или подпрограммы необходимо определить их с помощью функции my(список). Если переменная одна то скобки можно опустить.
my() декларирует private переменные в пределах текущей подпрограммы, блока, функции eval() или do/require/use файлов. Private переменные аналогичны auto переменным в С.
Пример:
# Программа вычисления факториала. print fact(3); # вычислить факториал 3*2*1 sub fact # Определяем подпрограмму. { my $m; # private переменная но не local ! $m = $_[0]; return 1 if $m <= 1; return($m * fact($m -1)); }
Можно указывать начальные значения private переменных как:
my(список) = выражение;
Так для вышеприведенного примера лучше было написать:
my($m) = $_[0];
В общем случае лучше использовать private переменные так-как это надежней и быстрее. private переменные обеспечивают лексическую область применения (видимости) а local - динамическую. Обычно это переменные форматов значение которых должно быть видимо из вызываемых подпрограмм. Применение функции local() не целесообразно в циклах так как она вызывается каждый раз и таким образом заметно замедляет время выполнения цикла.
Для краткого описаня типа параметров передаваемых подпрограмме можно применять прототипы. В Перл существуют следующие прототипы:
Декларация | Пример вызова |
---|---|
sub mylink($$) | mylink $old, $new |
sub myvec($$$) | myvec $var, $offset, 1 |
sub myindex($$;$) | myindex &getstring, "substr" |
sub myreverse(@) | myreverse $a, $b, $c |
sub myjoin($@) | myjoin ":",$a,$b,$c |
sub mypop(\@) | mypop @array |
sub mysplice(\@$$@) | mysplice @array, @array, 0, @pushme |
sub mykeys(\%) | mykeys %{$hashref} |
myopen HANDLE, $name | |
sub mypipe(**) | mypipe READHANDLE, WRITEHANDLE |
sub mygrep(&@) | mygrep { /foo/ } $a, $b, $c |
sub myrand($) | myrand 42 |
sub mytime() | mytime |
Здесь:
\'символ' | параметр с типом 'символ' |
'@' или '%' | все оставшиеся параметры как список |
'$' | скаляр |
'&' | безымянная подпрограмма |
'*' | ссылка на таблицу имен |
';' | разграничитель обязательных и не обязательных параметров |
Иногда нужно в качестве параметра передать подпрограмме не значение элемента массива а ссылку на него, что бы подпрограмма могла изменить значение элемента. Для этого в Перл к имени переменной добавляется символ '*' Подбное выражение называют 'type glob' так как в Юниксе символом '*' обозначают "все возможные значения". Поэтому '*' для массива означает "все элементы массива".
а переменная $AUTOLOAD будет содержать имя не существующей подпрограммы. Данный механизм очень одобен для средств отладки.