Есть ли какой-нибудь способ использовать “константу” в качестве хэш-ключа в Perl?
Вопрос
Есть ли какой-нибудь способ использовать константу в качестве хэш-ключа?
Например:
use constant X => 1;
my %x = (X => 'X');
Приведенный выше код создаст хэш с "X" в качестве ключа, а не с 1 в качестве ключа.Принимая во внимание, что я хочу использовать значение константы X в качестве ключа.
Решение
use constant
фактически создает постоянные подпрограммы.
Чтобы сделать то, что вы хотите, вам нужно явно вызвать sub:
use constant X => 1;
my %x = ( &X => 'X');
или
use constant X => 1;
my %x = ( X() => 'X');
Другие советы
Другой вариант - не использовать прагму use constant и переключиться на Readonly в соответствии с рекомендациями в Perl Best Practices Дэмиана Конвея.
Я переключился некоторое время назад, поняв, что постоянные ссылки на хэш - это просто постоянная ссылка на хэш, но ничего не делают с данными внутри хэша.
Синтаксис только для чтения создает переменные "обычного вида", но фактически обеспечивает постоянство или доступность только для чтения.Вы можете использовать его точно так же, как любую другую переменную в качестве ключа.
use Readonly;
Readonly my $CONSTANT => 'Some value';
$hash{$CONSTANT} = 1;
Ваша проблема в том, что => - это волшебная запятая, которая автоматически заключает слово в кавычки перед ним.Итак, то, что вы написали, эквивалентно ('X', 'X').
Самый простой способ - это просто использовать запятую:
my %x = (X, 'X');
Или вы можете добавить различные знаки препинания, чтобы у вас больше не было простого слова перед =>:
my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
Использование $hash{CONSTANT()}
или $hash{+CONSTANT}
чтобы предотвратить срабатывание механизма цитирования голых слов.
Большинство других людей хорошо ответили на ваш вопрос.Взятые вместе, они дают очень полное объяснение проблемы и рекомендуют обходные пути.Проблема в том, что прагма Perl "использовать константу" действительно создает подпрограмму в вашем текущем пакете, имя которой является первым аргументом прагмы, а значение - последним.
В Perl, как только подпрограмма объявлена, она может быть вызвана без скобок.
Понимая, что "константы" - это просто подпрограммы, вы можете понять, почему они не интерполируются в строках и почему оператор "жирной запятой" "=>", который заключает в кавычки левый аргумент, думает, что вы передали ему строку (попробуйте другие встроенные функции, такие как time() и keys(), иногда с жирной запятой для дополнительного удовольствия).
К счастью, вы можете вызвать константу, используя явные знаки препинания, такие как скобки или символ амперсанда.
Однако у меня есть к вам вопрос:почему вы вообще используете константы для хэш-ключей?
Я могу придумать несколько сценариев, которые могли бы привести вас в этом направлении:
Вы хотите контролировать, какие ключи могут быть в хэше.
Вы хотите абстрагировать названия ключей на случай, если они изменятся позже
В случае с номером 1 константы, вероятно, не сохранят ваш хэш.Вместо этого рассмотрите возможность создания класса с общедоступными установщиками и получателями, которые заполняют хэш, видимый только объекту.Это очень не похожее на Perl решение, но его очень легко выполнить.
В случае с номером 2 я бы по-прежнему решительно выступал за создание Класса.Если доступ к хэшу регулируется через четко определенный интерфейс, только разработчик класса несет ответственность за правильное получение имен ключей хэша.В этом случае я бы вообще не предлагал использовать константы.
Надеюсь, это поможет, и спасибо за ваше время.
Тот Самый use constant
pragma создает подпрограмму, прототип которой не принимает аргументов.В то время как это выглядит как и константа в стиле C, на самом деле это подпрограмма, которая возвращает постоянное значение.
Тот Самый =>
(жирная запятая) автоматически заключает левый операнд в кавычки, если это простое слово, как и обозначение $hash{key}.
Если ваше использование имени константы выглядит как простое слово, сработают механизмы цитирования, и вы получите ее имя в качестве ключа вместо ее значения.Чтобы предотвратить это, измените использование так, чтобы оно не было простым словом.Например:
use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;
В инициализаторах вы также можете использовать вместо них простую запятую:
%hash = (X, 1);
=> оператор интерпретирует свою левую часть как "строку", как это делает qw().
Попробуйте использовать
my %x = ( X, 'X');
Один из способов - инкапсулировать X как (X):
my %x ( (X) => 1 );
Другой вариант - отказаться от '=>' и использовать вместо этого ',':
my %x ( X, 1 );
Комментарий @shelfoo (репутация еще недостаточно высока, чтобы добавлять комментарий непосредственно туда!)
Полностью согласен с Дэмианом Конвеем относительно лучших практик Perl...его настоятельно рекомендуется прочитать.
Однако, пожалуйста, прочтите Комментарий К Рекомендации модуля PBP это полезная "опечатка", если вы планируете использовать PBP для внутреннего руководства по стилю.