Pergunta

Eu tenho um arquivo revs.pm:

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

E outro arquivo como importer.pl:

use revs;

Como posso acessar %vers a partir de importer.pl ?

Foi útil?

Solução

Criar um módulo adequado e alterar o minha palavra -chave para nosso:

# 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";

Outras dicas

Outra maneira convencional é usar o Exportador módulo em seu pacote, e exportar a variável:

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

Isso evita ter que usar o nome do pacote ao se referir à variável de importer.pl:

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

Uma desvantagem é que você deve garantir que seu nome de variável seja único para evitar colisões de nomes.

Como alternativa, você não pode apenas algumas partes do seu programa com uma variável global. Considere o que acontece quando você usa este hash em um módulo:

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;
    }
}

E então em algum outro módulo:

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

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

E então use os dois módulos:

use Foo;
use Bar;

some_other_function;
some_function;
some_other_function;

Dependendo $some_condition, Some_other_function produz resultados diferentes cada vez que você chama. Divirta -se depurando isso. (Isso é mais um each problema do que um problema global do estado; Mas, ao expor a implementação interna, você permite que seus chamadores façam coisas que você não pretendia, e que podem facilmente interromper seu programa.)

Também é uma dor reescrever Foo e Bar quando você troca o hash codificado para uma pesquisa de banco de dados sob demanda, por exemplo.

Portanto, a solução real é projetar uma API adequada e exportar que, em vez de toda a variável:

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;

Agora seu módulo é mais fácil de usar:

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;
}

Agora, alguma coisa não pode atrapalhar alguma coisa e quando você altera a implementação do get_component_version, o restante do seu programa não se importará.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top