2017-01-26 9 views
1

Я застреваю при создании модуля perl Moose.Как получить доступ к переменным в импортированном модуле в локальной области в perl?

У меня есть глобальный модуль pm.

package XYZ; 
require Exporter; 
our @ISA = qw(Exporter); ## EDIT missed this line 
our @EXPORT_OK = qw($VAR); 
my $VAR1 = 1; 
our $VAR = {'XYZ' => $VAR1}; 
1; 

Я хочу, чтобы получить $VAR в Moose модуле Я создаю

package THIS; 
use Moose; 
use YAML::XS; 
sub get_all_blocks{ 
    my ($self) = @_; 
    require $self->get_pkg(); # this returns the full path+name of the above package 
    # i cannot use use lib+use since the get_pkg starts complaining 

    our $VAR; 
    print YAML::XS::Dump($XYZ::VAR); # this works 
    print YAML::XS::Dump($VAR); # this does not work 
    # i cannot use the scope resolution since XYZ would keep changing. 

} 
1; 

Может кто-то пожалуйста, помогите мне с доступом к переменной?

EDIT: Пропущенная одна строка в коде package XYZ. я не могу коснуться package XYZ, так как он принадлежит/используется кем-то другим, я могу просто использовать его :(

+1

[Не экспортировать переменные!] (Http://perldoc.perl.org/Exporter.html#What-Not-to-Export) – ThisSuitIsBlackNot

+2

«Не экспортировать переменные» прикомандированные, но затем более общие - почему бы вам не использовать XYX qw (...) 'в вашем' THIS'? Вам нужны символы из других пакетов, поэтому импортируйте их. – zdim

+0

Я сделал односимвольное исправление. В пакете у вас был 'XYX', он был изменен на' XYZ'. Похоже на то, что вы намеревались. Если нет, не стесняйтесь возвращать мои изменения. – stevieb

ответ

1

Вы не хотите our $VAR; в пространстве имен THIS «s. Это создает лексическую ссылку на $THIS::VAR. Не то, что вы хотите .

Вместо этого вам нужно правильно use:

use XYZ qw($VAR); 

Однако XYZ не имеет import бежать здесь, так что вам нужно обновить, что есть два способа исправить., чтобы сделать это - нужно импортировать импорт, например, use Exporter qw(import);, а другой - вывести Exporter, например, use parent qw(Exporter);. Оба они получат XYZ->import(...) для правильной работы.

После XYZ является use ИНГ Exporter правильно, то use XYZ qw($VAR); линия будет вызывать Perl неявно загружаются XYZ и называют XYZ->import(qw($VAR)), которая будет импортировать эту переменную в пространстве имен.

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

4

Экспорт переменных может легко привести к неприятностям.

Почему не

package XYZ; 

use strict; 
use warnings; 

use Exporter qw(import); 
our @EXPORT_OK = qw(get_var); 

our $VAR = '...'; 

sub get_var { return $VAR } 

, а затем

package THIS; 

use warnings; 
use strict; 

use XYZ qw(get_var); 

my $var = get_var(); 

См Exporter.

Что касается того, что вы пытались сделать, есть две проблемы.

Во-первых, вы никогда не импортируете $VAR из XYZ в THIS. Если вам нужны символы из других пакетов, вам необходимо их импортировать. Эти пакеты должны сделать их доступными в первую очередь, поэтому вам нужно добавить их в @EXPORT_OK. Итак, вы использовали бы вышеуказанное, но с $VAR вместо get_var().

Другой способ - использовать @EXPORT, а затем эти символы вводятся в каждую программу, которая просто говорит use Package;.Я настоятельно рекомендую использовать только @EXPORT_OK, хотя вызывающим абонентам необходимо явно указать, что они хотят. Это также хорошо документирует то, что используется.

Даже после того, как вы добавите это, в THIS есть еще одна переменная, которая будет скрывать (маску, тень) $XYZ::VAR. Поэтому удалите our $VAR в THIS. Это отличный пример одной проблемы с глобалами. После того, как вы их представите, вы всегда должны быть осторожны, даже с переменными имен. Но есть проблемы с распределением переменных между модулями.

Это заставляет компоненты приложения запутываться, а код становится сложнее и труднее работать. Он противоречит принципам четко определенных областей и модульного дизайна, он позволяет действовать на расстоянии и т. Д. Perl предоставляет много хороших инструментов для структурирования кода, и нам редко нужны глобальные переменные и общие переменные. Он говорит, что сам Exporterwarns against that.

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

+0

@ user590222 Я добавил немного с момента публикации, вы можете прочитать его. Я не знаю, видели ли вы редактирование, таким образом, эту заметку. – zdim