468x60comp.hardware.ani.


| Содержание | Предисловие | В

Глава 8

    В этой главе:


Функции

Мы уже знакомы со встроенными пользовательскими функциями, например 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 world

say ("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 или 100

sub 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); # временная для хранения возвращаемого значения foreach $_ (@_) ( # проход по списку аргументов

push(@result,$_); # прибавить } )

return Oresult; # возвратить окончательный список }

Что, если бы нам понадобились все элементы, значения которых превышают 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 содержит значение

Обратите внимание: в этот раз мы использовали еще две локальные переменные, чтобы присвоить имена аргументам. Это весьма распрос

В результате выполнения операции 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

* "Обычная переменная" в этом случае переменная пакета (поэтому $х



|     Назад     |
| Содержание | Предисловие | В



Сайт создан в системе uCoz