Подтвердить что ты не робот

Есть ли способ использовать "константу" в качестве хеш-ключа в Perl?

Можно ли использовать константу как хэш-ключ?

Например:

use constant X => 1;

my %x = (X => 'X');

Вышеприведенный код создаст хэш с ключом "X", а не 1 как ключ. Принимая во внимание, что я хочу использовать значение константы X как клавишу.

4b9b3361

Ответ 1

use constant фактически выполняет постоянные подпрограммы.

Чтобы сделать то, что вы хотите, вам нужно явно вызвать sub:

use constant X => 1;

my %x = ( &X => 'X');

или

use constant X => 1;

my %x = ( X() => 'X');

Ответ 2

Другой вариант - не использовать постоянную прагму использования и переходить на Readonly в соответствии с рекомендациями в Perl Best Practices от Damian Conway.

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

Синтаксис readonly создает переменные "обычного вида", но фактически обеспечит постоянство или читаемость. Вы можете использовать его так же, как и любую другую переменную в качестве ключа.


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

Ответ 3

Ваша проблема в том, что = > - это волшебная запятая, которая автоматически цитирует слово перед ним. То, что вы написали, эквивалентно ( "X", "X" ).

Самый простой способ - просто использовать запятую:

my %x = (X, 'X');

Или вы можете добавить различные знаки пунктуации, чтобы у вас больше не было простого слова перед = > :

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );

Ответ 4

Используйте $hash{CONSTANT()} или $hash{+CONSTANT}, чтобы предотвратить использование механизма цитирования в виде слова.

От: http://perldoc.perl.org/constant.html

Ответ 5

Большинство других людей хорошо ответили на ваш вопрос. Взятые вместе, они создают очень полное объяснение проблемы и рекомендуют обходные пути. Проблема в том, что прагма Perl "use constant" действительно создает подпрограмму в вашем текущем пакете, чье имя является первым аргументом прагмы и значение которого является последним.

В Perl, как только объявлена ​​подпрограмма, она может быть вызвана без парнеров.

Понимая, что "константы" являются просто подпрограммами, вы можете понять, почему они не интерполируются в строках и почему оператор "жирной запятой" "= > ", который цитирует левый аргумент, считает, что вы передали ему строку ( попробуйте другие встроенные функции, такие как time() и keys() когда-нибудь с жирной запятой для дополнительного удовольствия).

К счастью, вы можете вызывать константу с помощью явной пунктуации, такой как parens или сингл амперсанда.

Однако у меня есть вопрос для вас: почему вы используете константы для хеш-ключей?

Я могу вспомнить несколько сценариев, которые могут привести вас в этом направлении:

  • Вы хотите контролировать, какие ключи могут находиться в хеше.

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

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

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

Надеюсь, что это поможет и спасибо за ваше время.

Ответ 6

Прагма use constant создает подпрограмму, прототипированную для принятия аргументов. Хотя он похож на константу C-стиля, это действительно подпрограмма, которая возвращает постоянное значение.

=> (жирная запятая) автоматически цитирует левый операнд, если его головоломка, как и нотация $hash {key}.

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

use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;

В инициализаторах вы также можете использовать обычную запятую:

%hash = (X, 1);

Ответ 7

Оператор

= > интерпретирует свою левую сторону как "строку", как это делает qw().

Попробуйте использовать

my %x = ( X, 'X');

Ответ 8

Одним из способов является инкапсуляция X как (X):

my %x ( (X) => 1 );

Другой вариант - покончить с '= > ' и вместо этого использовать ',':

my %x ( X, 1 );

Ответ 9

Комментарий @shelfoo (репутация недостаточно высокая, чтобы добавить комментарий прямо там еще!)

Полностью согласен с Perl Best Practices от Damian Conway... его очень рекомендуемое чтение.

Однако, пожалуйста, прочитайте комментарий к Рекомендации модуля PBP, который является полезной "ошибкой", если вы планируете использовать PBP для руководства по внутреннему стилю.