Импортированные переменные 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") - я не уверен в этом.

Другие вопросы по тегам