| Содержание | Предисловие | В |
Глава 8В этой главе:
Вызов пользовательской функции Возвращаемые значения Аргументы Локальные переменные в функциях Полулокальные переменные, созданные при помощи функции local Создаваемые операцией my() переменные файлового уровня Упражнения ФункцииМы уже знакомы со встроенными пользовательскими функциями, например chomp, print и другими, и пользовались ими. Теперь давОпределение пользовательской функции Пользовательская функция, чаще называемая подпрограммой, определяется в Perl-программе с помощью следующей конструкции: sub имя {оператор_1 ;оператор_2 ;оператор 3;} Здесь имя — это имя подпрограммы, которое может быть любым именем вроде тех, которые мы давали скалярным переменным, ма* Более правильно эту подпрограмму следовало бы назвать sfred, но пользоваться такого рода именами приходитсБлок операторов, следующий за именем подпрограммы, становится ее определением. Когда эта подпрограмма вызывается, то блок операторов, входящих в нее, выполняется, и вызывающему объекту выдается Вот, например, подпрограмма, которая выдает знаменитую фразу: sub say_hello ( print "hello, world!\n"; } Определения подпрограмм могут стоять в любом месте текста программы (при выполнении они пропускаются), но обычно их размещают в конце файла программы, чтобы основная часть программы находилась Определения подпрограмм глобальны*; локальных подпрограмм не бывает. Если у вас вдруг появились два определения подпрограмм с одинаковым именем, то второе определение заменяет первое без предупреждения**. В теле подпрограммы вы можете обращаться к переменным, используемым в других частях программы (глобальным переменным), и присваивать им значения. По умолчанию любая ссылка на переменную в теле подпрограммы относится к глобальной В следующем примере: sub say_what { print "hello, $what\n"; } переменная $what является глобальной переменной, которая может использоваться также и в других частях программы.Вызов пользовательской функции Для вызова подпрограммы из любого выражения необходимо поставить после ее имени круглые скобки, например: say_hello(); # простое выражение$а = 3 + say_hello() # часть более сложного выраженияfor ($х = start_value(); $х < end_value(); $х} t вызов трех подпрограмм для определения значений* Точнее, глобальны для текущего пакета, но поскольку в этой книге отдельные пакеты не рассматриваются, вы можете считать определения подпрограмм глобальными для всей прогр** Если только вы не выполняете программу с ключом -w.Одна подпрограмма может вызывать другую подпрограмму, которая, в свою очередь, может вызывать третью подпрограмму и т.д., пока вся наличная память не будет заполнена адресами возврата и не полн Возвращаемые значения Вызов подпрограммы почти всегда является частью некоторого выражения. Результат, полученный после выполнения подпрограммы, называется возвращаемым значением. Возвращаемое значени Давайте, например, определим такую подпрограмму: sub sum_of_a and_b ( return $a + $b; } Последнее выражение, вычисляемое в теле этой подпрограммы (фактически единственное вычисляемое выражение), — сумма переменных $а и$а = 3; $b = 4;$с = sum_of_a_and_b(); # $с присваивается значение 7 $d = 3 * sum_of_a_and_b(); # $dПри вычислении в списочном контексте подпрограмма может возвращать список значений. Рассмотрим такую подпрограмму и ее вызов: sub Ii st_o f_a_and_b { return($a,$b) ; } $a = 5; $b = 6; @c = list_of_a_and_b(); # @c присваивается значение (5,6)Последнее вычисленное выражение действительно означает последнее вычисленное выражение, а не последнее выражение, определенное в теле подпрограммы. Например, следующая подпрограмма возвращает $ sub gimme a_or_b ( if ($a > 0) ( print "choosing a ($a)\n"; returns $a; ) else ( print "choosing b ($b)\n"; returns $b; } } Все это довольно тривиальные примеры. Однако будет гораздо лучше, если вместо того, чтобы полагаться на глобальные переменные, мы сможем передавать в подпрограмму значения, разные для каждого в Аргументы Несомненно, подпрограммы, выполняющие одно определенное действие, полезны, однако перед вами откроются совершенно новые горизонты, когда вы сможете передавать в подпрограмму аргумент В Perl после вызова подпрограммы следует список, заключенный в круглые скобки, которые обеспечивают автоматическое присваивание элементов данного списка на период выполнsub say_hello_to ( print "hello, $_[0]!\n" # первый параметр }Здесь мы видим ссылку на $_[0] — первый элемент массива @_. Обратите внимание: несмотря на внешнее сходство, значениеsay_hello_to("world"); # выдает hello, world $х = "somebody";say_hello_to($x); # выдает hello, somebody say_hello_to("me")+say_hello_to("you"); # а теперь приветствует себя и васВ последней строке возвращаемые значения явно использованы не были, однако для определения суммы Perl сначала должен вычислить всеВот пример с использованием более одного параметра: sub say ( print "$_[0], $_[!]!\n"; } say("hello","world"); # опять hello worldsay ("goodbye", "cruel world"); # goodbye cruel world - популярная фраза из фильмовИзбыточные параметры игнорируются, т.е. если вы никогда не заглядываете в $_ [ 3 ], языку PerlПеременная @_ является локальной для подпрограммы. Если для @_ установлено глобальное значение, то оно перед вызовом подпрограммы сохраняется, а после возврата из подпрограммы восстанавливается Давайте вернемся к программе сложения а и b из предыдущего раздела. Вот подпрограмма, которая складывает любые два значения, а именно два значения, передаваемые в нее как паsub add_two { return $_[0] + $_[!]; 1 print add_two(3,4); # выводит значение 7$с = add_two(5,6); # $с получает значение 11Давайте обобщим эту подпрограмму. Что, если нам нужно сложить 3, 4 или 100sub add ( $sum = 0; # инициализировать суммуforeach $_ (@_) { $sum += $_; } return $sum # последнее вычисленное выражение: сумма всех элементов }$а = add(4,5,6); # складывает 4+5+6=15 и присваивает переменной $аЧто, если бы переменная с именем $sum использовалась у нас раньше? При вызове подпрограммы addЛокальные переменные в функциях Мы уже говорили о переменной @_ и о том, как для каждой подпрограммы, вызываемой с параметрами, создается локальная копия этой переменной. Вы можете создавать собственные скалярные пере sub add { ту ($sum); # сделать $sum локальной переменной $sum =0;<* foreach $_ (@_) ( $sum += $ ; # прибавить все элементы} return $sum # последнее вычисленное выражение: сумма всех элементов }Когда выполняется первый оператор в теле подпрограммы, текущее значение глобальной переменной $sum сохраняется и создается совершеВот способ создания списка всех элементов массива, значения которых превышают число 100:sub bigger_than_100 ( my (Oresult); # push(@result,$_); # прибавить } )return Oresult; # возвратить окончательный список }Что, если бы нам понадобились все элементы, значения которых превышают 50, а не 100? Пришлось бы отредактировать программу, замениsub bigger_than ( my($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 содержит значениеОбратите внимание: в этот раз мы использовали еще две локальные переменные, чтобы присвоить имена аргументам. Это — весьма распросВ результате выполнения операции my создается список, который можно использовать в левой части операции присваивания. Этому списку можно присваивать начальные значения для каждой из вновь созда my($n,@values) ; ($n,@values) = заменить на my($n,@values)= @_; Этот прием очень распространен в Perl. Локальным переменным, не являющимся аргументами, можно таким же способом присваивать литераmy($sum) = 0; # инициализировать локальную переменнуюИмейте в виду, что, несмотря на наличие объявления, my в действительности представляет собой выполняемую операцию. Стратегия правильной работы в PerlПолулокальные переменные, созданные при помощи функции localВ Perl существует еще один способ создания "частных" локальных переменных —tellmeO ; spoof() ; tellmeO ; sub spoof ( local ($value) = "temporary"; tellmeO ; > sub telime { print "Current value is $value\n"; } На выходе получаем следующее: Current value is original Current value is temporary Current value is original Если бы вместо local мы использовали my, то локальный вариант перемОперацию my можно использовать только для объявления простых скалярных переменных, переменных-массивов и хеш-переменных с буквен-но-цифровыми именами, тогда как для переменной local#1 и @argv, с помощью my объявлять нельзя, а вот с local они работаlocal $_; в начало любой подпрограммы, которая использует $_ для собственных нужд. Это гарантирует сохранность предыдущего значения и его авНа более серьезном уровне программирования вам, возможно, нужно будет знать, что переменные, создаваемые функцией local, — это, по сути дела, замаскированные глобальные переВ большинстве случаев рекомендуем использовать не local, a my, потому что эта операция действует быстрее и надежнее.Создаваемые операцией my() переменные файлового уровня Операцию my () можно также использовать на внешнем уровне программы, вне всех подпрограмм и блоков. Хотя в результате не бuse strict; * Прагма — это директива компилятора. Среди этих директив —Если поставить эту прагму в начало файла, то вы больше не сможете использовать переменные (скалярные, массивы и хеши), сначала не "объявив" их. Объявляются они с помощью операции my use strict; my $а; # сначала значение undef my @b = qw(fred barney betty); разве можно забыть про Вильму? @с = sort @b; # HE КОМПИЛИРУЕТСЯВо время компиляции последний оператор будет помечен флагом ошибки, потому что он обратился к переменной, не объявленной ранее с помощью операции my (т.е. @с). Другими словами, ваша программа д Преимущества принудительного объявления переменных таковы: 1. Ваши программы будут работать несколько быстрее (обращение к переменным, созданным с помощью my, производится несколько быстрее, чем к обычным переменным).*2. Гораздо быстрее будут выявляться ошибки набора, потому что вы большене сможете случайно обратиться к несуществующей переменной $ freed,когда вам будет нужна переменная $fred.По этой причине многие программисты, пишущие на Perl, автоматически начинают каждую новую программу прагмой use strict.Упражнения Ответы к упражнениям даны в приложении А. 1. Напишите подпрограмму, которая будет принимать в качестве аргумента числовое значение от 1 до 9<2. Взяв подпрограмму из предыдущего упражнения, напишите программу, которая будет брать два числа и складывать их, выдавая результат в формате Two plus two equals four.3. Модернизируйте эту подпрограмму так, чтобы она возвращала названия от negative nine до negative one* "Обычная переменная" в этом случае — переменная пакета (поэтому $х —
| Содержание | Предисловие | В
| |