При создании программы разработчику, как правило, приходится писать в разных ее местах практически идентичные последовательности операторов, выполняющие одни и те же функции. В подобной ситуации очень могут помочь процедуры и функции, которые представляют собой самостоятельные фрагменты программы, оформленные особым образом и снабженные уникальным именем. Упоминание этого имени в тексте программы называется вызовом процедуры (функции). В Perl, как и в «классических» языках программирования, отличие функции от процедуры заключается в том, что в результате ее исполнения всегда получается единственное значение. Поэтому обращение к функции можно использовать в выражениях наряду с переменными. Далее будем называть функцию или процедуру общим именем «подпрограмма».
Подпрограммы позволяют разбить программу на несколько независимых друг от друга частей. Это экономит память, поскольку каждая подпрограмма существует в единственном экземпляре, а обращаться к ней можно сколь угодно часто из разных точек программы. При вызове подпрограммы активизируется последовательность образующих ее операторов.
Ранее уже были описаны встроенные функции (подпрограммы), например chdir, print, mkdir, chomp, rmdir и другие. Теперь же рассмотрим функции, которые пользователь может определить самостоятельно. В Perl подпрограмма представляется конструкцией типа
sub ”название подпрограммы” { оператор_1; оператор_2; оператор_3; оператор_4; оператор_5; ... }
Названием подпрограммы может быть любое имя. Подчеркнем, что могут одновременно существовать разные структуры программы с одинаковыми именами. Например, скалярная переменная $users, массив @users, хэш %users и подпрограмма &users. Подпрограммы могут находиться в любом месте текста программы, но обычно их размещают в конце. В теле подпрограммы можно обращаться к переменным, используемым в других частях программы, т. е. к глобальным, и присваивать им значения. Так, в следующем примере:
sub welcome { print ”Welcome to CIA website!\n”; print ”————————————————\n”; print; print ”Hello, $who\n”; }
переменная $who является глобальной, и поэтому может быть использована и в других частях программы. Для вызова приведенной выше подпрограммы необходимо поставить либо перед ее именем амперсант, либо после ее названия круглые скобки, например
$who = ”Michael Yevdokimov”; &welcome; или $who = ”Michael Yevdokimov”; welcome();
Одна подпрограмма может вызывать другую, та, в свою очередь, третью и т. д. Результат, полученный после вызова подпрограммы, называется возвращаемым значением. Он выходит вследствие выполнения оператора return или последнего вычисленного выражения. Вызов подпрограммы почти всегда является частью некоторого выражения, это хорошо видно на приведенных ниже примерах.
Пример 1 $a = 5; $b = 10; $c = 3 * ∑ print ”Результат = $c\n”; # выводит Результат = 45 sub sum { return $a + $b; } Пример 2 $c = 3 * &sum(5,10); print ”Результат = $c\n”; # выводит Результат = 45 sub sum { return $_[0] + $_[1]; } Пример 3 @c = sum(5,10); # результат заносится в массив @c print ”Первое значение: $c[0]; Второе: $c[1]\n”; sub sum { return ($_[0],$_[1]); }
На период выполнения подпрограммы значения элементов списка параметров, заключенных в круглые скобки, автоматически присваиваются специальной переменной @_. Подпрограмма может обратиться к ней и получить число аргументов и их значения. В двух последних примерах ссылка $_[0] представляет собой обращение к первому элементу массива @_. Переменная @_ является локальной для подпрограммы. Если же для нее установлено глобальное значение, то перед вызовом подпрограммы оно сохраняется, а после возврата восстанавливается.
Подпрограмма также может передавать параметры в другую подпрограмму, не «теряя» значения собственной переменной @_. Вложенный вызов подпрограммы точно так же пользуется уже своей переменной с именем @_.
Подсчитаем факториал числа 5 (листинг 2).
Листинг 2 print &factorial(1..5); sub factorial{ $s=1; foreach $_ (@_) { # $s = $s * $_; # $_++; $s *= $_; # этой строчкой можно заменить две предыдущие } return $s; }
Для сложения чисел от 1 до 5 вместо
$s *= $_ ;
вставим строку
$s += $_;
Если бы переменная с именем $s уже использовалась в программе, то при вызове подпрограммы &factorial ее значение было бы потеряно. А теперь рассмотрим, как этого можно избежать. Чтобы ограничить область действия переменной в пределах какой-либо подпрограммы, ее нужно заключить в круглые скобки, а слева от них написать my:
sub factorial { my ($s); $s = 0; foreach $_ (@_) { $s += $_; } return $s; }
При этом текущее значение глобальной переменной $s запоминается, и после выполнения первого оператора в теле подпрограммы создается совершенно новая переменная с именем $s. При выходе из подпрограммы Perl восстанавливает предыдущее (глобальное) значение. Схема функционирует и в том случае, когда переменная $s является локальной, взятой из другой подпрограммы, вызывающей данную. Переменные могут иметь много вложенных локальных версий, но в каждый момент можно обращаться только к одной из них (листинг 3).
Листинг 3 $s = ”something”; print &factorial(1..5); print ”$s\n”; sub factorial { my($s)=1; # инициализировать локальную переменную # если эту строчку закомментировать, # то результатом будет вывод двух чисел, # тогда как с оператором my сначала будет # выведена строка, а затем число foreach $_ (@_) { $s *= $_; } return ”$s\n”; }
Следует также иметь в виду, что все операции my должны быть размещены в начале подпрограммы.
В некоторых программах на Perl можно встретить функцию local. С ее помощью создаются так называемые «полулокальные» переменные. Приведем пример использования local в программе (листинг 4).
Листинг 4 $value = ”good”; tellme(); spoof(); tellme(); sub spoof { local ($value) = ”bad”; tellme(); } sub tellme { print ”It is $value!\n”; }
Переменная, созданная с помощью функции my, значение которой равно «bad», доступна только в пределах подпрограммы spoof(), а за ее пределами $value по-прежнему остается равной «good». Такой же она будет и в подпрограмме tellme(), вызванной из spoof(). При использовании функции local локальное значение $value = «bad» становится глобальным для всех остальных подпрограмм, запущенных из spoof(), в частности для tellme. Иначе говоря, локальные переменные доступны для функций, вызываемых из той подпрограммы, в которой они объявлены.
Кроме того, операцию my можно использовать только для объявления простых скалярных переменных, переменных-массивов и хэш-переменных с буквенно-цифровыми именами, тогда как для переменной, описанной с помощью local, подобные ограничения не установлены. Встроенные переменные Perl, такие как $_, @ARGV и #1, нельзя объявлять с помощью my, а через local они работают прекрасно. Поскольку $_ используется в большинстве программ на Perl, целесообразно помещать строку
local $_;
в начало любой подпрограммы, где есть такое имя. Это сохраняет предыдущее значение и автоматически восстанавливает его при выходе из подпрограммы. В большинстве же остальных случаев опытные программисты на Perl рекомендуют применять my, а не local, так как эта операция работает быстрее и надежнее.
Назад | Содержание | Вперед