Можно ли использовать константу как хэш-ключ?
Например:
use constant X => 1;
my %x = (X => 'X');
Вышеприведенный код создаст хэш с ключом "X", а не 1 как ключ. Принимая во внимание, что я хочу использовать значение константы X как клавишу.
Можно ли использовать константу как хэш-ключ?
Например:
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');
Другой вариант - не использовать постоянную прагму использования и переходить на Readonly в соответствии с рекомендациями в Perl Best Practices от Damian Conway.
Я переключился некоторое время назад, осознав, что константный хэш-реф - это просто постоянная ссылка на хэш, но ничего не делайте с данными внутри хэша.
Синтаксис readonly создает переменные "обычного вида", но фактически обеспечит постоянство или читаемость. Вы можете использовать его так же, как и любую другую переменную в качестве ключа.
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 "use constant" действительно создает подпрограмму в вашем текущем пакете, чье имя является первым аргументом прагмы и значение которого является последним.
В Perl, как только объявлена подпрограмма, она может быть вызвана без парнеров.
Понимая, что "константы" являются просто подпрограммами, вы можете понять, почему они не интерполируются в строках и почему оператор "жирной запятой" "= > ", который цитирует левый аргумент, считает, что вы передали ему строку ( попробуйте другие встроенные функции, такие как time() и keys() когда-нибудь с жирной запятой для дополнительного удовольствия).
К счастью, вы можете вызывать константу с помощью явной пунктуации, такой как parens или сингл амперсанда.
Однако у меня есть вопрос для вас: почему вы используете константы для хеш-ключей?
Я могу вспомнить несколько сценариев, которые могут привести вас в этом направлении:
Вы хотите контролировать, какие ключи могут находиться в хеше.
Вы хотите абстрагировать имя ключей в случае, если эти изменения будут позже
В случае числа 1 константы, вероятно, не сохранят ваш хэш. Вместо этого подумайте о создании класса с публичными сеттерами и геттерами, которые заполняют хэш, видимый только объекту. Это очень не-Perl-решение, но очень легко сделать.
В случае с номером 2 я все равно решительно выступаю за класс. Если доступ к хэшу регулируется с помощью четко определенного интерфейса, то право на получение имен хеш-ключей отвечает только разработчик класса. В этом случае я бы не предложил использовать константы вообще.
Надеюсь, что это поможет и спасибо за ваше время.
Прагма use constant
создает подпрограмму, прототипированную для принятия аргументов. Хотя он похож на константу 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 Best Practices от Damian Conway... его очень рекомендуемое чтение.
Однако, пожалуйста, прочитайте комментарий к Рекомендации модуля PBP, который является полезной "ошибкой", если вы планируете использовать PBP для руководства по внутреннему стилю.