Вопрос

Я боролся с каким-то Perl, который использует хэш-ссылки.

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

$myhash{$key} |= {};

То есть "присвоите $myhash{$key} ссылку на пустой хэш, если только у него уже нет значения".

Однако разыменование этого и попытка использовать его в качестве ссылки на хэш привели к ошибкам интерпретатора при использовании строки в качестве ссылки на хэш.

Меняем его на:

if( ! exists $myhash{$key}) {
  $myhash{$key} = {};
}

...заставлял все работать.

Так что у меня нет проблема.Но мне любопытно, что там происходило.

Кто-нибудь может объяснить?

Это было полезно?

Решение

Причина, по которой вы видите ошибку об использовании строки в качестве ссылки на хэш, заключается в том, что вы используете неправильный оператор. |= означает "побитовый или присваивающий". Другими словами,

  $foo |= $bar;

это то же самое , что

  $foo = $foo | $bar

Что происходит в вашем примере, так это то, что ваша новая анонимная хэш-ссылка становится строковой, а затем побитовой со значением $myhash{$key}.Чтобы еще больше запутать дело, если $myhash{$key} на данный момент значение не определено, это простая строка ссылки на хэш, которая выглядит следующим образом HASH(0x80fc284).Поэтому, если вы проведете беглый осмотр конструкции, это может посмотри похоже на ссылку на хэш, но это не так.Вот несколько полезных результатов с помощью Data::Dumper:

   perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
   $VAR1 = {
             'foo' => 'HASH(0x80fc284)'
           };

И вот что вы получаете, когда используете правильный оператор:

  perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
  $VAR1 = {
            'foo' => {}
          };

Другие советы

В Perl есть сокращенные операторы присваивания.Тот Самый ||= operator часто используется для установки значений по умолчанию для переменных из-за особенности Perl, заключающейся в том, что логические операторы возвращают последнее вычисленное значение.Проблема в том, что вы использовали |= который является побитовый или вместо ||= который является логичный или.

Начиная с Perl 5.10, лучше использовать //= вместо этого. // является логическим оператором defined-or и не завершается ошибкой в угловом случае, когда текущее значение определено, но равно false.

Я думаю, ваша проблема заключалась в использовании "|=" (побитовое-или присваивание) вместо "||=" (присвоить, если значение равно false).

Обратите внимание, что ваш новый код не совсем эквивалентен.Разница в том , что "$myhash{$key} ||= {}" заменит существующие, но ложные значения ссылкой на хэш, но новое значение этого не сделает.На практике это, вероятно, не имеет значения.

Попробуй это:

my %myhash;
$myhash{$key} ||= {};

Вы не можете объявить хэш элемент в my оговорка, насколько я знаю.Сначала вы объявляете хэш, а затем добавляете в него элемент.

Редактировать:Я вижу, вы достали my.Как насчет того, чтобы попробовать ||= вместо того, чтобы |=?Первое является идиоматическим для "ленивой" инициализации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top