Как я могу импортировать константы в несколько модулей в Perl? - PullRequest
5 голосов
/ 08 февраля 2009

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

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

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

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

Ответы [ 5 ]

7 голосов
/ 06 июля 2011

Этот кусок кода должен делать именно то, что вы хотите. Отправить все похвалы 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__."::"};
}
7 голосов
/ 08 февраля 2009

Проверьте Экспортер и справочную страницу perlmod.

5 голосов
/ 09 февраля 2009

Не говорите никому, что я говорил вам это, но специальные переменные 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 и т. Д.)

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

2 голосов
/ 11 февраля 2009

Вы можете использовать Экспортер , например:

In Constants.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 ();
2 голосов
/ 08 февраля 2009

Вы можете поставить это наверху 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?

...