Как я могу условно использовать модуль в Perl? - PullRequest
16 голосов
/ 15 октября 2010

Я хочу сделать что-то подобное в Perl:

$Module1="ReportHashFile1"; # ReportHashFile1.pm
$Module2="ReportHashFile2"; # ReportHashFile2.pm

if(Condition1)
{
  use $Module1;
}
elsif(Condition2)
{
  use $Module2;
}

ReportHashFile * .pm содержит пакет ReportHashFile *.

Также, как ссылаться на массив внутри модуля на основе динамического имени модуля?

@Array= @$Module1::Array_inside_module;

Могу ли я в любом случае этого добиться? Какая-то директива компилятора?

Ответы [ 3 ]

23 голосов
/ 15 октября 2010

Для этого может пригодиться модуль if.

В противном случае основная идея заключается в использовании require, который происходит во время выполнения, вместо use, который происходит во время компиляции. Обратите внимание, что '

BEGIN {
    my $module = $condition ? $Module1 : $Module2;
    my $file = $module;
    $file =~ s[::][/]g;
    $file .= '.pm';
    require $file;
    $module->import;
}

Что касается адресации глобальных переменных, может быть проще, если вы просто экспортировали переменную или функцию, возвращающую ее вызывающей стороне, которую вы могли бы использовать по ее безусловному имени. В противном случае есть также возможность использовать метод и вызывать его как $Module->method_name.

В качестве альтернативы, вы можете использовать символические ссылки, как описано в perlref. Однако, это обычно довольно неприятный запах.

my @array = do {
    no strict 'refs';
    @{ ${ "${Module}::Array_inside_module" } };
};
8 голосов
/ 16 октября 2010

Если скорость выполнения не важна, вы можете использовать строку eval :

if (Condition1) {
    eval "use $Module1"; die $@ if $@;
}
elsif (Condition2) {
    eval "use $Module2"; die $@ if $@;
}
5 голосов
/ 16 октября 2010

Люди уже говорили вам, как вы можете загрузить модуль с помощью примитивов Perl. Также есть Module :: Load :: Conditional .

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

  package ReportHashFileFoo;
  our @some_package_variable;
  sub get_array { \@some_package_variable }

Затем, когда вы загружаете этот модуль:

  if( ... some condition ... ) {
       eval "use $module" or croak ...;
       my $array_ref = $module->get_array;
       }

Я не знаю, что вы на самом деле делаете ( XY Проблема ), но, вероятно, есть лучший дизайн. Когда такие вещи кажутся хитрыми, обычно это потому, что вы упускаете лучший способ сделать это.

...