Как импортировать все «наши» переменные из неназванного модуля Perl, не перечисляя их? - PullRequest
9 голосов
/ 12 сентября 2011

Мне нужно импортировать все наши переменные из неназванного модуля Perl (Module.pm) и использовать их внутри скрипта Perl (Script.pl).

Следующий код хорошо работает без «строгого использования» , но с ним не получилось.Как я могу изменить этот код для работы с «использовать строгий» без ручного перечисления всех импортированных переменных (как описано в ответе на другой вопрос )?

Большое спасибо за вашу помощь!

Script.pl:

use strict;
require Module;
print $Var1;

Module.pm:

our $Var1 = "1\n";
...
our $VarN = "N\n";
return 1;

Запустите скрипт:

$> perl Script.pl

Ошибки:

Global symbol "$Var1" requires explicit package name at Script.pl line 3.
Execution of Script.pl aborted due to compilation errors.

ПРИМЕЧАНИЕ (1) : модуль не имеет названия, поэтому использование префикса Module:: не вариант.

ПРИМЕЧАНИЕ (2) : Module.pm содержит также набор функций, настроенных глобальными переменными.

ПРИМЕЧАНИЕ (3) : Переменные отличаются и НЕ должны храниться в одном массиве.

ПРИМЕЧАНИЕ (4) : Дизайн НЕ хорош, но вопрос не в дизайне.Речь идет о том, чтобы заставить указанный код работать с минимальными изменениями со сложностью O(1), то есть с несколькими строками кода, которые не зависят от N.

Solution Candidate (ACCEPTED): Добавить $:: перед всеми импортированными переменными.Он соответствует strict, а также позволяет отличать my переменные от imported в коде.

Ответы [ 4 ]

7 голосов
/ 12 сентября 2011

Измените ваш скрипт на:

use strict;
require Module;
print $Module::Var1;

Проблема в том, что $Var1 не в основном пространстве имен, а в Module.

Редактировать: Как указано в комментариях ниже, вы не назвали свой модуль (то есть он не говорит package Module; вверху). Из-за этого нет пространства имен Module. Измените ваш скрипт на:

use strict;
require Module;
print $main::Var1;

... позволяет скрипту правильно распечатать 1\n.

4 голосов
/ 12 сентября 2011

Если вам нужно импортировать все наши переменные в каждом модуле, то с вашим дизайном что-то серьезно не так.Я предлагаю вам перепроектировать вашу программу, чтобы разделить элементы, чтобы между ними было минимальное количество перекрестных разговоров.Это называется развязка .

2 голосов
/ 13 сентября 2011

Вы хотите экспортировать все переменные из модуля, и вы хотите сделать это таким образом, чтобы вы даже не знали, что экспортируете? Забудьте о use strict и use warnings, потому что, если вы поместите их в свою программу, они просто будут кричать и свернуться калачиком в углу, истерически плача.

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

Давайте посмотрим на возможные проблемы с вашей идеей.

  1. Вы не представляете, что экспортируется в ваш модуль. Как программа, использующая этот модуль, узнает, что использовать? Где-то вы должны документировать, что переменные $foo и @bar доступны для использования. Если вам нужно сделать это, почему бы просто не позаботиться об этом?
  2. У вас есть проблема, когда кто-то меняет модуль, и внезапно новая переменная экспортируется в программу с использованием этого модуля. Представьте, если эта переменная уже используется. В программе неожиданно обнаружена ошибка, и вы никогда не сможете ее исправить.
  3. Вы экспортируете переменную в свой модуль, и разработчик решает изменить эту переменную или даже удаляет ее из программы. Опять же, поскольку вы понятия не имеете, что импортируется или экспортируется, нет способа узнать, почему в программе внезапно появилась ошибка.

Как я уже говорил, у вас есть , чтобы знать где-нибудь, что используется в вашем модуле, который может использовать программа, так что вы все равно должны это документировать. Если вы собираетесь настаивать на импорте переменных, используйте хотя бы массив EXPORT_OK и модуль Exporter. Это поможет ограничить ущерб. Таким образом, ваша программа может объявлять, от каких переменных она зависит, а ваш модуль может объявлять, какие переменные, как он знает, могут использовать программы. Если я изменяю модуль, я был бы очень осторожен с любой переменной, которую я вижу, я экспортирую. И, если вы должны указать в своей программе, какие переменные вы импортируете, вы должны быть осторожны с этими конкретными переменными.

В противном случае зачем использовать модули? Почему бы просто не вернуться к Perl 3.0 и использовать require вместо use и забыть об использовании оператора package.

1 голос
/ 12 сентября 2011

Похоже, у вас есть данные в файле, и вы пытаетесь загрузить эти данные в вашу программу.

Как и сейчас, объявления our в модуле объявляют только переменные для области действия этого файла. Как только файл завершится, для доступа к переменным вам необходимо использовать их полное имя. Если ваш модуль имеет строку package xyz;, то полное имя - $xzy::Var1. Если декларация package отсутствует, используется пакет по умолчанию main, в котором переменным присваивается имя $main::Var1

.

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

Измените ваш модуль на что-то вроде:

@My::Module::Data = ("1\n", "2\n" ... )

, а затем получить доступ к элементам по индексу:

$My::Module::Data[1]
...