Цель лекции: освоить приемы использования в программе готовых модулей, а также научиться создавать собственные модули и управлять пространствами имен в программе с помощью пакетов.
Современные языки программирования предоставляют программистам средства для того, чтобы упорядочить свои наработки. Нетривиальная программа обычно представляет из себя некоторое количество файлов с исходными текстами, расположенных в нескольких каталогах. А большие программные комплексы образуют внушительную иерархию подкаталогов, содержащих десятки и сотни программных файлов. Универсальные подпрограммы принято сохранять в отдельных библиотечных файлах, чтобы обращаться к ним из разных программ. Сходные по назначению процедуры и функции объединяются в библиотеки подпрограмм. Библиотека программ на Perl - это файл, обычно с суффиксом .pl, где хранится произвольный набор подпрограмм для использования в других программах. (Этот суффикс иногда применяется для прикладных программ на Perl, но для них рекомендуется использовать суффикс .plx.) Для примера напишем небольшую программную библиотеку для работы с данными о музыкальных дисках и сохраним ее в файле 'lib/music_lib.pl':
# библиотека подпрограмм 'music_lib.pl'
sub albums_by_artist { # найти альбомы указанного артиста
my ($artist) = @_; # аргумент поиска: артист
my @albums = (); # возвращаемый список
seek DATA, 0, 0; # ищем с начала файла
while (<DATA>) { # просматриваем альбомы в файле
push @albums, $1 if /$artist;(.+?);/; # и выбираем
} # все подходящие
return @albums; # результат: список альбомов
}
# ... другие подпрограммы библиотеки...
__DATA__ # конец библиотечного файла
Рассмотрим, как происходит обращение к библиотечным подпрограммам во время выполнения программы.
Чтобы воспользоваться подпрограммой из библиотечного файла, нужно в вызывающей программе загрузить библиотеку командой do 'file.pl'. Команда do загружает любую Perl-программу из внешнего файла во время выполнения программы. Причем в библиотеке в свою очередь могут загружаться программные файлы по команде do. Кроме этого, do регистрирует загруженные программы в специальном хэше %INC. Если do не может найти или прочитать файл, она возвращает неопределенное значение undef и присваивает специальной переменной $! признак ошибки. Если do прочитала файл, но не может его скомпилировать, она возвращает undef и помещает сообщение об ошибке в специальную переменную .$@. Если файл успешно скомпилирован, do возвращает значение последнего вычисленного выражения.
После того как внешний файл был успешно загружен, можно вызывать подпрограммы из загруженного библиотечного файла, как если бы они были описаны в текущей программе. В нашем случае это будет выглядеть так:
do 'lib/music_lib.pl'; # загрузить библиотеку
# вызвать библиотечную подпрограмму
my @albums = albums_by_artist('Elton John');
print "$_\n" foreach(@albums); # напечатать найденный список
Обратите внимание, что в нашем примере явно указан путь к подкаталогу с библиотекой, что предполагает запуск программы из определенного каталога. Гораздо лучше сделать так, чтобы расположение библиотек не зависело от местонахождения вызывающей программы. Для этого в Perl имеется специальный массив @INC, в котором хранится список каталогов для поиска загружаемых исходных файлов. В этот массив по умолчанию включаются каталоги, где находятся системные библиотеки Perl. Чтобы на время выполнения программы добавить в этот список свои каталоги с библиотеками, можно воспользоваться опцией -I, указываемой в командной строке при запуске компилятора perl. Например, запустим на выполнение программу и укажем дополнительно искать файлы в каталоге /Shock/Mike/lib и его подкаталогах:
perl -I/Shock/Mike/lib program.pl
Тогда в программе можно указывать путь к библиотекам относительно одного из перечисленных в массиве @INC каталогов:
do 'music_lib.pl'; # искать библиотеку в списке @INC
Другой способ добавить в массив @INC каталог для поиска загружаемых файлов - использовать директиву (прагму) use lib. Для этого в программе перед командой загрузки библиотеки нужно указать ее расположение, например так:
use lib('/Shock/Mike/lib'); # добавить путь к списку @INC
Команда загрузки внешних программ do считается устаревшей и употребляется все реже и реже. Вместо нее применяется команда require, имеющая целый ряд преимуществ. Эта команда вызывает ошибку, если загружаемая программа не найдена в массиве @INC, компилируется с ошибками или не возвращает истинного значения. Поэтому в конце загружаемого файла должно быть любое выражение, возвращающее истинное значение. По устоявшейся традиции выражение '1;' помещается в последней исполняемой строке файла. Поэтому, чтобы библиотека в нашем примере без ошибок загружалась командой require, в конце библиотечного файла добавим требуемую строку: