Есть ли способ использовать «константу» в качестве хеш-ключа в Perl? - PullRequest
31 голосов
/ 19 сентября 2008

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

Например:

use constant X => 1;

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

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

Ответы [ 9 ]

45 голосов
/ 19 сентября 2008

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

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

use constant X => 1;

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

или

use constant X => 1;

my %x = ( X() => 'X');
19 голосов
/ 19 сентября 2008

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

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

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


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

14 голосов
/ 19 сентября 2008

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

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

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

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

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
9 голосов
/ 19 сентября 2008

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

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

6 голосов
/ 19 сентября 2008

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

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

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

К счастью, вы можете вызывать константу, используя явную пунктуацию, например, символ "Паренс" или "Амперсанд".

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

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

  1. Вы хотите контролировать, какие ключи могут быть в хэше.

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

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

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

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

5 голосов
/ 19 сентября 2008

Прагма use constant создает прототип подпрограммы без аргументов. Хотя выглядит как константа в стиле C, на самом деле это подпрограмма, которая возвращает постоянное значение.

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

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

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

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

%hash = (X, 1);
2 голосов
/ 19 сентября 2008

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

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

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

my %x ( X, 1 );
2 голосов
/ 19 сентября 2008

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

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

my %x = ( X, 'X');
1 голос
/ 22 сентября 2008

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

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

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

...