Локальные переменные в функциях
Мы уже говорили о переменной @_ и о том, как для каждой подпрограммы, вызываемой с параметрами, создается локальная копия этой переменной. Вы можете создавать собственные скалярные переменные, переменные-массивы и хеш-переменные, которые будут работать точно так же. Это делается с помощью операции ту, которая получает список имен переменных и создает их локальные версии (или реализации,
если вам так больше нравятся). Вот снова функция add, на этот раз построенная на основе операции ту:
sub add {
ту ($sum); # сделать $sum локальной переменной $sum =0; # инициализировать сумму
*
foreach $_ (@_) (
$sum += $ ; # прибавить все элементы
}
return $sum # последнее вычисленное выражение: сумма всех элементов }
Когда выполняется первый оператор в теле подпрограммы, текущее значение глобальной переменной $sum сохраняется и создается совершенно новая переменная с именем $sum (и значением undef). При выходе из подпрограммы Perl отбрасывает эту локальную переменную и восстанавливает предыдущее (глобальное) значение. Эта схема работает даже в том случае, если переменная $sum в текущий момент является локальной переменной, взятой из другой подпрограммы (той, которая вызывает данную подпрограмму, или той, которая вызывает ту, которая вызывает данную подпрограмму, и т.д.). Переменные могут иметь много вложенных локальных версий, но одновременно разрешается обращаться только к одной из них.
Вот способ создания списка всех элементов массива, значения которых превышают число 100:
sub bigger_than_100 (
my (Oresult); # временная для хранения возвращаемого значения foreach $_ (@_) ( # проход по списку аргументов if ($_ > 100) ( # подходит?
push(@result,$_); # прибавить } )
return Oresult; # возвратить окончательный список }
Что, если бы нам понадобились все элементы, значения которых превышают 50, а не 100? Пришлось бы отредактировать программу, заменив 100 на 50. А если бы нам было нужно и то, и другое? В этом случае следовало бы заменить 50 или 100 ссылкой на переменную. Тогда программа выглядела бы так:
sub bigger_than (
my($n,@values); # создать локальные переменные ($n,@values) = @_; # выделить из списка аргументов значение предела
# и элементы массива my (@result); # временная переменная для хранения возвращаемого
4 значения
foreach $_ (@values) ( # проход по списку аргументов if ($_ > $n) { # подходит?
push(Oresult,$_); # прибавить } )
@result; t возвратить окончательный список }
# примеры вызова:
@new = bigger_than(100,@list); # @new содержит все значения Olist > 100 @this " bigger_than(5,l,5,15,30); # @this содержит значение (15,30)
Обратите внимание: в этот раз мы использовали еще две локальные переменные, чтобы присвоить имена аргументам. Это — весьма распространенная практика, потому что гораздо удобнее (да и безопаснее) использовать переменные $п и $values, чем указывать $_[0] и @_[1. . $#_].
В результате выполнения операции my создается список, который можно использовать в левой части операции присваивания. Этому списку можно присваивать начальные значения для каждой из вновь созданных переменных. (Если значения списку не присвоить, то новые переменные вначале получат значение undef, как и любая другая переменная.) Это значит, что мы можем объединить первые два оператора этой подпрограммы, т.е. операторы
my($n,@values) ;
($n,@values) = @_; # выделить из списка аргументов значение предела # и элементы массива
заменить на
my($n,@values)= @_;
Этот прием очень распространен в Perl. Локальным переменным, не являющимся аргументами, можно таким же способом присваивать литеральные значения, например:
my($sum) = 0; # инициализировать локальную переменную
Имейте в виду, что, несмотря на наличие объявления, my в действительности представляет собой выполняемую операцию. Стратегия правильной работы в Perl состоит в том, что все операции my должны быть размещены в начале определения подпрограммы, до того, как начинается реализация основных выполняемых в ней действий.