Использование констант в Perl

Я пытаюсь определить константы в Perl с помощью constant прагма:

use constant {
    FOO => "bar",
    BAR => "foo"
};

Я сталкиваюсь с небольшим количеством проблемы и надеюсь, что существует стандартный способ обработать ее.

В первую очередь...

Я определяю сценарий рычага для Подверсии. Для создания вещей простыми я хочу иметь единственный файл, где класс (пакет), который я использую, находится в том же файле как мой фактический сценарий.

Большей части этого пакета вовлекут константы в него:

 print "This is my program";

 package MyClass;

 use constant {
    FOO => "bar"
 };

 sub new { ... }

Я хотел бы свою константу FOO быть доступным для моей основной программы. Я хотел бы сделать это, не имея необходимость относиться к нему как MyClass::FOO. Обычно, когда пакет является отдельным файлом, я мог сделать это в своей основной программе:

use MyClass qw(FOO);

но, так как мой класс и программа являются единственным файлом, я не могу сделать этого. Каков был бы лучший способ для моей основной программы, чтобы смочь получить доступ к моим константам, определенным в моем классе?

Второй выпуск...

Я хотел бы использовать постоянные величины в качестве ключей хеша:

$myHash{FOO} = "bar";

Проблема - это %myHash имеет литеральную строку FOO как ключ а не значение константы. Это вызывает проблемы, когда я делаю вещи как это:

if (defined $myHash{FOO}) {
   print "Key " . FOO . " does exist!\n";
}

Я мог вызвать контекст:

if (defined $myHash{"" . FOO . ""}) {

Я мог добавить круглые скобки:

if (defined $myHash{FOO()}) {

Или, я мог использовать временную переменную:

my $foo = FOO;
if (defined $myHash{$foo}) {

Ни один из них не действительно хорошие способы обработать эту проблему. Так, каков лучший способ? Есть ли один способ, которым я отсутствую?

Между прочим, я не хочу использовать Readonly::Scalar потому что это 1). медленный и 2). не часть стандартного пакета Perl. Я хочу определить свой рычаг, чтобы не потребовать дополнительных пакетов Perl и быть максимально простым работать.

13
задан Michael Carman 16 June 2010 в 21:41
поделиться

4 ответа

Если вы хотите сохранить все в одном файле, вы можете определить свой пакет констант следующим образом:

use warnings;
use strict;

BEGIN {  # BEGIN means this will all happen at compile time
    package Constants;

    $INC{'Constants.pm'}++;     # tell `require` that the package is loaded
    use base 'Exporter';        # setup package to export
    our @EXPORT_OK = qw( PI );  # what to export

    use constant PI => 3.14159; # define your constant
}

package main;

use Constants qw( PI );  # use it like normal

print PI;

Затем, чтобы обмануть автоматическое цитирование внутри хеш-индексов, вы можете написать его так: $ hash { + PI} или $ hash {(PI)} или $ hash {PI ()} или $ hash {& PI} или $ hash {:: PI} ... Возможно, я мог бы продолжить, но я думаю, вы поняли.

Причина, по которой требуется $ INC {'Constants.pm'} ++ , заключается в том, что строка use Constants qw (PI); действительно означает:

BEGIN {
    require 'Constants.pm';
    Constants->import( qw( PI ) );
}

И require проверит % INC , чтобы узнать, загружен ли уже пакет. Таким образом, присвоив ему истинное значение (в данном случае 1), require 'Constants.pm'; часть использования перестанет работать.

20
ответ дан 1 December 2019 в 21:11
поделиться
  1. Константы Perl не являются константами. Они определены при компиляции как особый вид функции, которая встроена во время компиляции.

  2. Я считаю, что использование «констант» Perl - это больше проблема, чем не использовать. Итак, обычно мой подход заключается в использовании скаляров со всеми прописными буквами. мой $ PI = 3,14159; .

4
ответ дан 1 December 2019 в 21:11
поделиться

Я второй ответ Эрика Строма.

Однако есть другой способ (но он слишком сильно раскрывает реализацию Perl):

use strict;
use warnings;

package Constants;
sub FOO() { 'bar' }
sub BAR() { 'foo' }
sub main::FOO() { FOO }
sub main::BAR() { BAR }

package main;

print FOO, BAR, "\n";
0
ответ дан 1 December 2019 в 21:11
поделиться

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

$myHash{FOO}   = 'bar'; # doesn't work, bareword quoted
$myHash{+FOO}  = 'bar'; # okay
$myHash{&FOO}  = 'bar'; # okay
$myHash{FOO()} = 'bar'; # okay

Экспорт функций и переменных из одного пакета в другой - это все манипуляции с таблицей символов. Модуль Exporter упрощает для нас эту задачу, но это не так сложно сделать без модуля.

package main;
sub stuff { return &FOO x 3 }
*FOO = *MyClass::FOO;
print stuff();               # "barbarbar"

package MyClass;
use constant FOO => "bar";

Вы также могли бы указать

BEGIN { *main::FOO = *FOO }

в пакете MyClass .

3
ответ дан 1 December 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: