В Perl как я могу импортировать хеш из библиотеки? - PullRequest
2 голосов
/ 04 марта 2010

У меня есть файл revs.pm:

my %vers = ( foo => "bar" );

И еще один файл, например importer.pl:

use revs;

Как мне получить доступ к %vers с importer.pl?

Ответы [ 3 ]

13 голосов
/ 04 марта 2010

Создайте подходящий модуль и измените ключевое слово my на our :

# revs.pm
package revs;

our %vers = ( foo => "bar" );

1; # Perl modules need to return a boolean "true" value.

# importer.pl
use revs;

print $revs::vers{foo} . "\n";
9 голосов
/ 04 марта 2010

Другим обычным способом является использование модуля Exporter в вашем пакете и экспорт переменной:

package revs;
use strict;
use warnings;
require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(%vers);
our %vers   = (foo=>'bar');
1;

Это позволяет избежать использования имени пакета при обращении к переменной из importer.pl:

use strict;
use warnings;
use Data::Dumper;
use revs;
print Dumper(\%vers);

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

6 голосов
/ 04 марта 2010

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

package Foo;
use MyApp::Versions qw(%versions); # i'm going to pretend that you didn't call the module "revs".

some_function {
    while(my ($k, $v) = each %versions){
       return if $some_condition;
    }
}

А потом в каком-то другом модуле:

package Bar;
use MyApp::Versions qw(%versions);

some_other_function {
    while(my ($k, $v) = each %versions){
       print "$k => $v\n";
    }
}

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

use Foo;
use Bar;

some_other_function;
some_function;
some_other_function;

В зависимости от $some_condition, some_other_function производит разные результаты каждый раз, когда вы называете это. Получайте удовольствие отлаживая это. (Это скорее проблема each, чем проблема глобального состояния; но выставляя внутренняя реализация, вы позволяете своим абонентам делать то, что Вы не собирались, и это может легко сломать вашу программу.)

Также сложно переписать Foo и Bar, когда вы меняете жестко запрограммированный код. хэш для поиска в базе данных по требованию, например.

Таким образом, реальным решением является разработка правильного API и экспорт этого вместо всей переменной:

package MyApp::Versions;
use strict;
use Carp qw(confess);
use Sub::Exporter -setup => {
    exports => ['get_component_version'],
};

my %component_versions = ( foo => 42 ); # yes, "my", not "our".

sub get_component_version {
    my ($component) = @_;
    return $component_versions{$component} ||
        confess "No component $component!"
}

1;

Теперь ваш модуль проще в использовании:

package Foo;
use MyApp::Versions qw(get_component_version);

sub some_function {
    die 'your foo is too old'
        unless get_component_version('foo') >= 69;

    return FooComponent->oh_hai;
}

Теперь some_function не может испортить some_other_function, и когда вы изменить реализацию get_component_version, остальные ваши программа не заботится.

...