- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования Perl - Михаил Шохирев
Шрифт:
Интервал:
Закладка:
Хотя подпрограмма может изменять значения глобальных переменных в вызывающей программе, требования надежности предписывают всегда передавать исходные данные в подпрограмму в виде аргументов, а результат ее работы получать в виде возвращаемого значения.
По той же причине, по которой подпрограмма не может возвращать несколько списков, она не может получать несколько отдельных списков в виде аргументов. Например, если подпрограмма вызвана так: subr1(@array1, @array2), то ей будет передан объединенный список из элементов двух массивов @array1 и @array2. Поэтому если необходимо передать несколько списочных объектов, то передаются ссылки на них, например: subr1(@array1, @array2).
При необходимости можно объявить подпрограмму до ее использования (forward declaration), а определение ее отнести в конец программного файла. При объявлении тело подпрограммы не записывается. Например:
sub factorial; # вычислить факториал числа
В объявлении подпрограмм могут указываться прототипы, о которых речь пойдет немного позднее в этой лекции.
Подпрограммы в Perl вызываются, когда их имя употребляется в каком-либо выражении. В этот момент выполняются определенные в подпрограмме действия, а выражение получает возвращенный подпрограммой результат. Хотя довольно часто возвращаемое подпрограммой значение игнорируется. Про такое обращение к подпрограмме говорят, что она вызвана в пустом контексте (void context). Минимальное выражение для вызова подпрограммы состоит из одного имени подпрограммы, и это выражение превращается в предложение программы, когда после него стоит точка с запятой. Вот пример выражения, состоящего только из вызова подпрограммы в пустом (безразличном) контексте:
yellow_submarine('We all live in a');
Кстати, в пустом контексте можно употреблять любые другие выражения, хотя, конечно, смысл в этом есть далеко не всегда:
2 * 2; # результат отброшен, есть смысл, если стоит... 'Истина где-то рядом'; # ...в конце подпрограммы $x++; # используется ради побочного эффекта
Обращение к подпрограмме может записываться различными способами - главное, чтобы компилятор Рerl мог определить, что встретившийся идентификатор - это имя вызываемой подпрограммы. Дать подсказку об этом компилятору можно по-разному. В ранних версиях Perl при вызове перед именем подпрограммы требовался разыменовывающий префикс &. Например:
&sub_without_parameters; # вызов подпрограммы без параметров &sub_with_parameters($arg1, $arg2); # и с параметрами
В современном Perl эта устаревшая форма вызова с префиксом & допустима и иногда используется. Гораздо чаще обращение к подпрограмме обозначается использованием круглых скобок после имени подпрограммы, даже если она вызывается без параметров. Как в этих примерах:
format_c(); # вызов подпрограммы без параметров format_text($text, $font, $size); # и с параметрами
Чтобы обращаться к пользовательской подпрограмме в стиле встроенных функций без круглых скобок, нужно чтобы определение или объявление подпрограммы было известно компилятору раньше ее вызова.
sub circle; # объявление пользовательской функции $area_of_circle = circle $radius; # вызов функции sub circle { # определение пользовательской функции return 3.141592653*$_[0]*$_[0]; # площадь круга }
В Perl эффективно реализована рекурсия, поэтому традиционные рекурсивные алгоритмы можно оформлять в виде вызова в подпрограмме самой себя. Например, как в классической функции вычисления факториала:
sub factorial ($) { # вычислить N! my $n = shift; return ($n <= 1) ? 1 : $n * factorial($n-1); }
Для разработки универсальных подпрограмм программисту нужно знать, в каком контексте была вызвана подпрограмма - какого возвращаемого значения от нее ожидают. Для этого в Perl предусмотрена функция wantarray(). Она возвращает истинное значение, если подпрограмма вызвана в списочном контексте, ложное значение, если подпрограмма вызвана в скалярном контексте, и неопределенное значение, если подпрограмма вызвана в пустом контексте. Проверка ожидаемого значения в подпрограмме и примеры ее вызова могут выглядеть так:
sub list_or_scalar { my @result = fill_result(); # формируем результаты if (!defined wantarray) { # пустой контекст - return; # не возвращаем значения } elsif (wantarray) { # списочный контекст - return @result; # возвращаем список } else { # скалярный контекст - return "@result"; # возвращаем скаляр } } list_or_scalar(); # вызов в пустом контексте my @list = list_or_scalar(); # вызов в списочном контексте my $scalar = list_or_scalar(); # вызов в скалярном контексте
В Perl программисту предоставляется возможность выполнить во время компиляции ограниченную проверку количества и типов параметров у подпрограммы. Это делается с помощью прототипа списка параметров. Для этого в определении и в объявлении подпрограммы после ее имени в круглых скобках указывается прототип. Прототип представляет из себя последовательность разыменовывающих суффиксов, определяющих количество параметров подпрограммы и типы их контекстов. Вот несколько примеров определения подпрограмм с прототипами:
# определение подпрограммы с 1-м параметром-скаляром sub list_mp3 ($) { my $path = $_[0]; # ... } # определение подпрограммы c 2-мя скалярными параметрами sub translate ([email protected]) { # и списком скаляров my ($from_lang, $to_lang, @words) = @_; # ... } sub generate_test(); # объявление подпрограммы без параметров
Для подпрограмм, определенных с прототипами, компилятор контролирует количество передаваемых аргументов и устанавливает ожидаемый подпрограммой контекст для каждого из аргументов. В приведенном далее вызове подпрограммы вместо массива ей будет передано количество элементов массива, поскольку прототип подпрограммы устанавливает скалярный контекст для единственного аргумента:
list_mp3 @dirs; # будет передан 1 скаляр: scalar @dirs
Перечень символов, применяемых для описания прототипов, с примерами определения подпрограмм приведен в таблице 12.1.
Таблица 12.1. Обозначение прототипов подпрограммПрототипТребования к параметрамПример определения / описанияПример вызова()отсутствие аргументовsub mytime ()mytime;$скалярное значениеsub myrand ($) sub myrename ($$)myrand 100; myrename $old, $new;@список скалярных значений (поглощает остальные параметры, поэтому употребляется последним в списке)sub myreverse (@) sub myjoin ([email protected])myreverse $a, $b, $c; myjoin ':', $x, $y, $z;&подпрограммаsub mygrep (&@)mygrep {/pat/} $a, $b, $c;*элемент таблицы символов (например, дескриптор файла)sub myopen (*$)myopen HANDLE, $name;взятие ссылки на следующий за ней прототипsub mykeys (%) sub mypop (@) sub mypush(@@)mykeys %hash; mypop @array; mypush @stack, $a, $b;;разделитель обязательных параметров от необязательных (в конце списка)sub mysubstr ($$;$)mysubstr $str, $pos; mysubstr $str, $pos, $length;
Проверки на соответствие прототипам не выполняются, если подпрограмма вызывается устаревшим способом (с префиксом &), а также для методов и подпрограмм, вызываемых через ссылки.
Скалярные переменные могут хранить ссылки не только на данные, но и на подпрограммы. В операции взятия ссылки имя подпрограммы должно использоваться с разыменовывающим префиксом &, как это показано в следующем примере:
$ref2max = &max; # взятие ссылки на подпрограмму sub max { # вычисляет максимум из списка значений my $maximum = shift; foreach (@_) { $maximum = $_ if ($_ > $maximum); } return $maximum; } print ref($ref2max); # будет выведено: CODE
Первый способ обращения к подпрограмме через ссылочную переменную оформляется аналогично обращению к элементу массива или хэша: после имени переменной, содержащей ссылку на подпрограмму, записывается операция разыменования ссылки (->), за которой обязательно указываются круглые скобки (со списком аргументов или без него), которые показывают, что это обращение к подпрограмме:
$max_of_list = $ref2max->(@list_of_numbers);
Другая форма обращения к подпрограмме с использованием ссылочной переменной предполагает использование префикса &:
$max_of_list = &$ref2max(@list_of_numbers); # можно окружить ссылочную переменную фигурными скобками $max_of_list = &{$ref2max}(@list_of_numbers);

