Как я могу сделать модуль, который импортирует много модулей для пользователя? - PullRequest
4 голосов
/ 19 августа 2010

У меня довольно сложная структура данных, которую я реализовал в Perl. Это было разбито на около 20 классов. По сути, каждый раз, когда вы хотите использовать один из этих классов, вам необходимо использовать все из них.

Прямо сейчас, если кто-то хочет использовать эту структуру данных, ему нужно сделать что-то вроде:

use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;

чтобы иметь возможность манипулировать всеми его частями. Как я могу написать модуль, который делает это для пользователя, так что все, что им нужно сделать, это

use Component;

чтобы импортировать все остальные модули?

В данном конкретном случае все модули являются классами и не имеют экспорта.

Ответы [ 5 ]

6 голосов
/ 19 августа 2010

Если это просто классы (т. Е. Они не экспортируют какие-либо функции или переменные, когда вы use их), тогда все, что действительно имеет значение, это то, что они были загружены.

Просто создайте Component.pm:

package Component;

our $VERSION = '1.00';

use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;

1; # Package return value

Вам не нужно Exporter или что-то в этом роде.

Однако вместо использования модуля, который представляет собой не что иное, как операторы use, это, вероятно, имеет больше смыслапоместить эти операторы use в класс корневого узла или в модуль, который создает структуру данных.То есть люди захотят сказать:

use Component::Root;
my $root = Component::Root->new(...);

или

use Component qw(build_structure);
my $root = build_structure(...);

в зависимости от того, как обычно создается ваша структура данных.Люди могут немного запутаться, написав:

use Component;
my $root = Component::Root->new(...);

, но это действительно зависит от того, как выглядит ваш API.Если есть несколько классов, на которые люди могут звонить new, то use Component может быть подходящим вариантом.

1 голос
/ 19 августа 2010
  • Вы можете использовать метод export_to_level для всех тех пакетов, которые являются Exporter с.

    MyPackage->export_to_level($where_to_export, $package, @what_to_export);
    
  • Вы также можете просто экспортировать все импортированные символы.

    use PackageA qw<Huey Dewey Louie>;
    ...
    our @ISA = qw<Exporter>; #inherit Exporter
    our @EXPORT = qw<Huey Dewey Louie>;
    
  • Однако, если вы не хотите экспортировать какие-либо символы и просто хотите загрузить модули, просто включите эти операторы use выше, и любой пакет в процессе будет возможность создавать их как классы, скажем, все ли они были ОО-модулями.

    При условии, что они были успешно загружены, они будут существовать в %INC и таблице символов.

0 голосов
/ 20 августа 2010

Модуль Modern :: Perl рекламирует себя как «включить все возможности Modern Perl одной командой», где эта команда

use Modern::Perl;

и эти функции

На данный момент это включает только прагмы строгого режима и предупреждения, а также все функции, доступные в Perl 5.10. Это также включает порядок разрешения метода C3; см. perldoc mro для объяснения.

Это много для одной строки кода, которая согласно документации perlmod в точности эквивалентна

BEGIN { require Module; import Module; }

Рассмотрим реализацию Modern :: Perl :

package Modern::Perl;

our $VERSION = '1.03';

use 5.010_000;

use strict;
use warnings;

use mro     ();
use feature ();

sub import {
    warnings->import();
    strict->import();
    feature->import( ':5.10' );
    mro::set_mro( scalar caller(), 'c3' );
}

1; # End of Modern::Perl

Чтобы адаптировать это к вашей ситуации, из вашего модуля верхнего уровня use всех других модулей, которые вы хотите загрузить, и вызовите их импорт, если таковой имеется, из MyTopLevelModule::import.

Обратите внимание, что вам не обязательно копировать

use 5.010_000;

в MyTopLevelModule.pm, но это было бы хорошей идеей! В соответствии с use документацией :

В особой форме use VERSION, VERSION может быть либо положительной десятичной дробью, такой как 5.006, которая будет сравниваться с $], либо v-строкой вида v5.6.1, который будет сравниваться с $^V (он же $PERL_VERSION). Исключение возникает, если VERSION больше, чем версия текущего интерпретатора Perl; Perl не будет пытаться проанализировать остальную часть файла. Сравните с require, который может выполнить аналогичную проверку во время выполнения.

0 голосов
/ 20 августа 2010

Если модули ничего не экспортируют и не имеют метода импорта (те же требования, что и в ответе cjm), вам просто нужно загрузить модули без импорта:

package Component;

our $VERSION = '1.00';

require Component::Root;
require Component::Foo;
require Component::Bar;
require Component::Baz;
require Component::Flib;
require Component::Zen;
require Component::Zen::Foo;
require Component::Zen::Bar;
require Component::Zen::Baz;
... # 15 more of these...
require Component::Last;

1; # Package return value

Пользователи модуля будутпросто сделайте:

require Component;

Если, однако, некоторые модули экспортируют, вам придется вызвать их метод import.Итак, вы добавили метод import в ваш модуль Component, который будет вызывать их:

sub import
{
    Component::Root->import;
    Component::Foo->import;
    ...
}

, и поэтому пользователям модуля придется use it:

use Component;

Обратите внимание, что вам, возможно, придется использовать некоторые другие приемы, если импортированный модуль должен вставлять символы в контексте импортера.Посмотрите, например, как импорт POE делает это.

0 голосов
/ 19 августа 2010

Moose :: Exporter , кажется, делает это, хотя все остальные ваши модули также должны будут использовать его.

В Component:

Moose::Exporter->setup_import_methods(
    also => [qw/Component::Root Component::..*/],
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...