Выпуск 25. Март 2015
← Про переменные и сигнатуры в Perl 6 | Содержание | Обзор CPAN за февраль 2015 г. →Модули в Perl 6
Краткий обзор основных моментов, которые полезно знать при работе с модулями в Perl 6
Тем, кто знаком с модулями в Perl 5, без труда разберутся с тем, как использовать их в Perl 6. Тем не менее, есть несколько важных отличий, которые необходимо знать перед началом работы.
Модули хранятся в файлах с тем же расширением .pm
. Точно так же организуется иерархия: модуль X::Y
компилятор будет искать в файле X/Y.pm
в одном из предопределенных каталогов или в каталоге, указанном в опции -I
при запуске из командной строки.
В теории, имена модулей не обязаны быть привязаны к файлам (а на практике сейчас имя модуля, указанное в самом модуле, похоже, вообще не используется). Однако пока про это, видимо, лучше не думать. Еще одна интересная особенность, а именно, возможность хранить и подключать один и тот же модуль, но разных версий, пока в Rakudo не реализована.
module
Модуль объявляется ключевым словом module
, за которым следует название. Возможны два варианта. Объявление может быть в виде директивы в начале файла, и весь остаток файла будет телом модуля:
module X;
sub x() {
say "X::x()";
}
Второй вариант — поместить тело модуля в блок:
module X {
sub x() {
say "X::x()";
}
}
export
Переменные (my
, our
) и функции (sub
), определяемые внутри модуля, по умолчанию не видны за его пределами. Для того, чтобы экспортировать имя, необходимо указать свойство (trait) is export
:
module X;
sub x() is export {
say "X::x()";
}
Это все, что требуется для того, чтобы функцией x()
удалось воспользоваться в программе, которая будет использовать модуль. Никаких многословных конструкций и манипулирования массивами @EXPORT
и @EXPORT_OK
больше не требуется.
use
Подключение модуля — простая операция с помощью ключевого слова use
.
Сначала создаем файл Greet.pm
:
module Greet;
sub hey($name) is export {
say "Hey, $name!";
}
А затем используем его:
use Greet;
hey("you"); # Hey, you!
Точно так же все работает, если имя модуля более сложное. В этом случае все импортируемые имена оказываются в текущей области видимости.
Файл Greet/Polite.pm
с модулем Greet::Polite
:
module Greet::Polite {
sub hello($name) is export {
say "Hello, $name!";
}
}
И программа, его использующая:
use Greet;
use Greet::Polite;
hey("you"); # функция из модуля Greet
hello("Mr. X"); # из Greet::Polite
import
Ключевое слово use
автоматически выполняет импорт имен из подключаемого модуля. Однако, если модуль определен в текущем файле в лексической области видимости (обратите внимание, что можно указать модуль локальным, написав my module
), автоматический импорт не произойдет, и придется сделать его явно:
my module M {
sub f($x) is export {
return $x;
}
}
import M;
say f(42);
Без принудительного импорта (import M;
) обращение к функции f()
из модуля приведет к ошибке. Причем импорту подвергнутся только имена, помеченные на экспорт конструкцией is export
.
Обратите внимание, что импорт происходит при компиляции, поэтому имена станут доступны в программе даже выше строки про импорт:
my module M {
. . .
}
say f(1);
import M;
say f(2);
need
Если же возникнет необходимость просто загрузить модуль, но ничего из него не импортировать, следует воспользоваться ключевым словом need
.
Создаем модуль N
с методом n()
(метод создан как our
— это важно, но без is export
— а это не так важно):
module N;
our sub n() {
say "N::n()";
}
И теперь указываем, что нужен этот модуль, а потом напрямую обращаемся к его методу:
need N;
N::n();
Последовательность use M; import M;
(именно в таком порядке) аналогична одному use M;
.
require
Ключевое слово require
позволяет загрузить модуль не во время компиляции (как это делает use
), а во время исполнения.
Для примера — модуль с единственной функцией, возвращающей сумму переданных ей аргументов:
module Math;
our sub sum(*@a) {
return [+] @a;
}
(Звездочка в *@a
нужна, чтобы Perl свернул все аргументы в один массив, и можно было бы написать sum(1, 2, 3)
. Без звездочки это станет синтаксической ошибкой, поскольку метод будет ожидать массив, а не три скаляра.)
Теперь подключаем модуль с помощью require
и вызываем функцию:
require Math;
say Math::sum(24..42); # 627
Если попытаться вызвать Math::sum()
до require
, программа не сможет найти нужное имя. При этом импортировать метод, написав import Math;
, тоже не получится, поскольку импорт происходит на этапе компиляции, то есть до того, как require
загрузит модуль.
Заключение
Для удобства, вот список ключевых слов Perl 6, которые потребуются при работе с модулями:
use
— загрузка и импорт на этапе компиляции;need
— загрузка без импорта на этапе компиляции;import
— импорт имен из загруженного модуля на этапе компиляции;require
— загрузка без импорта во время исполнения.
← Про переменные и сигнатуры в Perl 6 | Содержание | Обзор CPAN за февраль 2015 г. →