Импортированные переменные perl импорт без значения
РЕШЕНО: Как оказалось, моя проблема коренится в том, что я не помещал $ перед DEBUGVAR в назначении @EXPORT_OK и "use config_global qw(config DEBUGVAR);" линия. Так как это не вызывает никаких ошибок, я не мог знать, что это была проблема. Итак, исправление заключается в том, чтобы поместить правильный синтаксис перед вашими переменными в этих точках.
Поэтому я пытаюсь научиться писать и импортировать модули Perl. Я не знаю, почему это было так трудно сделать, но у меня много проблем с этой, казалось бы, тривиальной задачей. Вот содержимое моего модуля:
package global_config;
use strict;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(DEBUGVAR);
our ($DEBUGVAR);
our $DEBUGVAR = "Hello, World!";
return 1;
Вот содержимое моего perl-скрипта, который импортирует модуль:
use strict;
use config_global qw(config, DEBUGVAR);
our %config;
our $DEBUGVAR;
print "variable imported with value: ".$DEBUGVAR;
Вывод:"переменная импортирована со значением:" и ничего больше. Моя переменная, кажется, теряет свое значение. Что я делаю неправильно?
РЕДАКТИРОВАТЬ: После того, как немного поковырялся и включил предупреждения, я выделил проблему в том, что $DEBUGVAR фактически никогда не импортируется. Когда я использую его через $config_global:DEBUGVAR, он работает как положено. Проблема в том, что он не импортируется в пространство имен. Что дает?
4 ответа
Я вижу несколько вопросов:
- Вы не должны использовать запятую в
qw()
синтаксис.qw
берет каждую разделенную пробелом фразу и помещает ее в элемент массива.
Эти два одинаковы:
my @bar = qw(foo bar barfu); #No commas!
my @bar = ("foo", "bar", "barfu"); #Commas Required
- Если вы экспортируете переменную, вам нужно поставить перед ней символ.
У тебя есть:
our @EXPORT_OK = qw(DEBUGVAR);
Так должно быть:
our @EXPORT_OK = qw($DEBUGVAR);
- Вы должны использовать более новый синтаксис Exporter:
Вот новый синтаксис Exporter:
package global_config;
use strict;
use warnings;
use Exporter 'import'; #Not "require". No need for "@ISA"
our @EXPORT_OK = qw(DEBUGVAR);
our $DEBUGVAR = "Hello, World";
1; #Makes no real difference, but you shouldn't say "return 1". Just standard.
- Наконец, что вы делаете, экспортируя переменные? Это просто плохая практика.
- Экспорт чего-либо теперь ставится под сомнение - даже функции. Это загрязняет пространство имен пользователя. (По крайней мере вы используете
@EXPORT_OKAY
). Посмотрите на File:: Spec. По умолчанию он использует полностью определенные имена пакетов для своих подпрограмм. - Рассматриваемая переменная доступна через полное имя пакета
$global_config::DEBUGVAR
, так что нет необходимости экспортировать его. - Что делать, если все это сделали? Да, вы в последний раз слышали об этом оправдании в детском саду, но это применимо здесь. Представьте, если экспортировано несколько модулей
$DEBUGVAR
,
- Экспорт чего-либо теперь ставится под сомнение - даже функции. Это загрязняет пространство имен пользователя. (По крайней мере вы используете
Существует несколько способов решения этой проблемы, но лучше всего использовать объектно-ориентированный Perl, чтобы помочь установить эту переменную и даже позволить пользователям изменять ее.
package MyPackage;
use strict;
use warnings;
use feature qw(say);
sub new {
my $class = shift;
my $debug = shift; #Optional Debug Value
my $self = {};
bless $self, $class;
if (not defined $debug) {
$debug = "Hello, world!";
$self->Debug($debug);
return $self;
}
sub Debug {
my $self = shift;
my $debug = shift;
if (defined $debug) {
$self->{DEBUG} = $debug;
}
return $debug;
}
1;
Чтобы использовать этот модуль, я просто создаю новый объект, и Debug будет установлен для меня:
use strict;
use warnings;
use MyPackage #No exporting needed
#Create an object w/ Debug value;
my $obj = MyPackage->new; #Debug is the default.
say $obj->Debug; #Prints "Hello, world!"
# Change the value of Debug
$obj->Debug("Foo!");
say $obj->Debug; #Now prints "Foo!"
#Create a new object with a different default debug
$obj2 = MyPackage->new("Bar!");
say $obj2->Debug; #Print "Bar!";
Это решает несколько вопросов:
- Это позволяет несколько значений отладки, потому что каждый объект теперь имеет свои собственные значения
- Не беспокойтесь о загрязнении пространства имен или доступе к переменным пакета. Опять же, все, что вам нужно, содержится в самом объекте.
- Проблемы легче отлаживать, поскольку сложность скрыта внутри самих объектов.
- Это новый предпочтительный метод, так что вы также можете привыкнуть к синтаксису и иметь возможность читать объектно-ориентированный код Perl. Вы будете видеть это все больше и больше.
Хотя экспорт переменных из пакета не обязательно является рекомендуемой практикой, для этого необходимо использовать фактическое имя экспортируемой переменной. В этом случае это $DEBUGVAR
и не DEBUGVAR
который будет именем подпрограммы.
В сценарии, использующем модуль конфигурации, вам не нужно объявлять $DEBUGVAR
переменная как our
, поскольку импортируемые переменные освобождены от строгих переменных.
Вы перепутали название, это выглядит так:
use config_global ...
package global_config;
Хотя можно подумать, что будет выдавать предупреждения. Если вы не используете предупреждения...?
ETA:
our @EXPORT_OK = qw($DEBUGVAR);
^
Кроме того, у вас есть два объявления для этой переменной. Вы действительно должны использовать предупреждения при отладке, иначе вы никогда не получите ничего.
Вы уверены, что хотите запятую здесь:
use config_global qw(config, DEBUGVAR);
Кроме того, вы не экспортируете конфигурацию, поэтому она может работать лучше:
use config_global qw(DEBUGVAR);
Я бы тоже убрал последний our $DEBUGVAR;
поскольку он может установить значение undef (или, по крайней мере, поставить его перед строкой "use") - я не уверен в этом.