Как я могу импортировать константы в несколько модулей Perl?

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

#Constants.pm
$h0 = 0;
$scale = 20;

А затем используйте их без уточнения с помощью main:: или Constants:: в нескольких модулях. Однако, если я напишу use Constants; более чем в одном модуле, они будут импортированы только в одно пространство имен. Есть ли способ обойти это?

Я использую последнюю версию ActivePerl.


person Lev    schedule 08.02.2009    source источник


Ответы (5)


Вы можете поместить это вверху Constants.pm:

package main;

В этом случае все определяемые вами переменные будут находиться в пространстве имен main:

$main::x

или если вы чувствуете себя смелым:

package;

В этом случае все определяемые вами переменные будут находиться в пустом пространстве имен:

$::x

Обратите внимание, что использование package без пространства имен не рекомендуется и, по-видимому, будет объявлено устаревшим в некоторых версиях Perl. См. цитату ниже.


Цитата из man perlfunc:


       package NAMESPACE
       package Declares the compilation unit as being in the given
               namespace.  The scope of the package declaration is
               from the declaration itself through the end of the
               enclosing block, file, or eval (the same as the "my"
               operator).  All further unqualified dynamic identifiers
               will be in this namespace.  A package statement affects
               only dynamic variables--including those you've used
               "local" on--but not lexical variables, which are cre?
               ated with "my".  Typically it would be the first decla?
               ration in a file to be included by the "require" or
               "use" operator.  You can switch into a package in more
               than one place; it merely influences which symbol table
               is used by the compiler for the rest of that block.
               You can refer to variables and filehandles in other
               packages by prefixing the identifier with the package
               name and a double colon:  $Package::Variable.  If the
               package name is null, the "main" package as assumed.
               That is, $::sail is equivalent to $main::sail (as well
               as to $main'sail, still seen in older code).

               If NAMESPACE is omitted, then there is no current pack?
               age, and all identifiers must be fully qualified or
               lexicals.  However, you are strongly advised not to
               make use of this feature. Its use can cause unexpected
               behaviour, even crashing some versions of Perl. It is
               deprecated, and will be removed from a future release.


Изменить: Этот вопрос также может быть полезен: Как использовать константы из модуля Perl?

person Nathan Fellman    schedule 08.02.2009
comment
Спасибо. Что мне действительно нужно, так это часть об исключении main. - person Lev; 08.02.2009
comment
Мне интересно, действительно ли это работает. Если это произойдет, я удалю отказ от ответственности в верхней части ответа. - person Nathan Fellman; 08.02.2009
comment
Это помещает константы в main::, но теперь вам нужно добавлять ко всем константам префикс main:: - person brian d foy; 09.02.2009
comment
Натан: Это работает. Брайан: Нет, вам нужно только добавить к ним префикс $::. Это терпимо. - person Lev; 09.02.2009
comment
FWIW, Perl 5.10 отказывается анализировать пакет. - person jrockway; 09.02.2009
comment
Почему использование $:: лучше, чем экспорт переменных в текущее пространство имен? Мне просто интересно.... - person Joe Casadonte; 10.02.2009
comment
Возможно нет. Лев только что сказал, что это терпимо. Лев, вы можете рассмотреть возможность использования Exporter, как предлагает Джо Касадонте. - person Nathan Fellman; 11.02.2009

Ознакомьтесь с Exporter и perlmod справочной страницей.

person Joe Casadonte    schedule 08.02.2009

Этот фрагмент кода должен делать именно то, что вы хотите. Отправьте все благодарности lkundrak.

package Constants;

use base qw/Exporter/;

use constant BOB => 666;
use constant ALICE => 555;

sub import {
    no strict "refs";

    ${[caller]->[0].'::'}{$_} = ${__PACKAGE__."::"}{$_}
        foreach grep { not /^(ISA|isa|BEGIN|import|Dumper)$/ } 
            keys %{__PACKAGE__."::"};
}
person Michal Ingeli    schedule 06.07.2011
comment
Забавно, что это единственный ответ, который касается констант (и даже вопрос на самом деле их не касается). - person Cornelius; 28.09.2011

Никому не говорите, что я вам это говорил, но специальные переменные Perl доступны везде. Вы, наверное, заметили, что это не работает:

{ package Foo;
our $global = 42; }

{ package Bar;
say "global is $global"; }

Это потому, что $global на самом деле называется $Foo::global. Вы также, вероятно, заметили, что это «правило» не применяется к таким вещам, как @INC, %ENV, $_ и т. д. Это потому, что предполагается, что эти переменные всегда находятся в main.

Но на самом деле это больше, чем просто эти переменные. Весь глобус "загоняется" в main. Это означает, что вы можете написать что-то вроде этого:

{ package Constants;
  $_{PI} = 3.141592; }

{ package Foo;
  say "pi is $_{PI}"; }

и это будет работать.

(То же самое относится к $ENV, &INC и т. д.)

Однако, если вы когда-нибудь сделаете это в реальном коде, ожидайте, что кто-то вас убьет :) Однако это полезно знать, на случай, если вы увидите, что кто-то другой делает это.

person jrockway    schedule 09.02.2009

Вы можете использовать Exporter следующим образом:

В константах.pm:

#Constants.pm
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw($h0 $scale);
@EXPORT_OK = qw(myfunc);

$h0 = 0;
$scale = 20;
sub myfunc {...}

Примечания:
* & в &myfunc в массиве @EXPORT является необязательным, и вам не рекомендуется его использовать. * Это будет экспортировать $h0 и $scale по умолчанию, и &myfunc, только если это запрошено явно (см. ниже, как указать, какие символы импортируются клиентским модулем)

А затем в модуле, который импортирует Constants.pm и хочет использовать $h0, $scale или &myfunc, вы добавляете следующее, чтобы импортировать все символы, которые находятся в @EXPORT в Constants.pm.

#MyModule.pm
use Constants qw(;

Если вы хотите импортировать только некоторые символы, используйте:

#MyModule.pm
use Constants qw($h0);

И, наконец, если вы не хотите импортировать какие-либо символы из Constant.pm, используйте:

#MyModule.pm
use Constants ();
person Nathan Fellman    schedule 11.02.2009