Почему ссылки сжаты в списках Perl? - PullRequest
5 голосов
/ 18 июня 2010

Помещение скомпилированного регулярного выражения в два разных хеша, на которые есть ссылки в списке:

my @list = ();

my $regex = qr/ABC/;

push @list, { 'one' => $regex };
push @list, { 'two' => $regex };

use Data::Dumper;
print Dumper(\@list);

Я бы ожидал:

$VAR1 = [
      {
        'one' => qr/(?-xism:ABC)/
      },
      {
        'two' => qr/(?-xism:ABC)/
      }
    ];

Но вместо этого мы получаем круговую ссылку:

$VAR1 = [
      {
        'one' => qr/(?-xism:ABC)/
      },
      {
        'two' => $VAR1->[0]{'one'}
      }
    ];

Это произойдет с бесконечно вложенными хеш-ссылками и неглубоко скопированными $regex.

Я предполагаю, что основная причина в том, что предварительно скомпилированные регулярные выражения на самом деле являются ссылками, а ссылки внутри одной и той же структуры списка уплотняются как оптимизация (\ $ scalar ведет себя так же). Я не совсем вижу полезности этого (вероятно, ссылка на ссылку имеет тот же объем памяти), но, возможно, есть причина, основанная на внутреннем представлении

Это правильное поведение? Могу ли я остановить это? Помимо возможного усложнения GC, эти круговые структуры создают довольно серьезные головные боли. Например, итерирование по списку запросов, которые иногда могут содержать одно и то же регулярное выражение, приведет к сбою драйвера MongoDB с неприятной ошибкой сегмента (см. https://rt.cpan.org/Public/Bug/Display.html?id=58500)

Ответы [ 3 ]

9 голосов
/ 18 июня 2010

Это ожидаемое поведение.

Ваша ссылка на самом деле не круглая; у вас есть два отдельных элемента, которые указывают на одну и ту же вещь. Data :: Dumper печатает удобочитаемое Perl-доступное представление ваших структур данных в памяти, и это действительно означает, что и $list[0]->{one}, и $list[1]->{two} указывают на одно и то же.

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

6 голосов
/ 18 июня 2010

Ничего смешного здесь не происходит.

  1. Вы сохранили одну и ту же ссылку дважды в одной и той же структуре данных.
  2. Затем вы попросили Data :: Dumper напечатать представление этой структуры.
  3. Data :: Dumper хочет как можно точнее обойти данные, которые вы предоставляете, что означает, что ему нужно вывести код Perl, который сгенерирует структуру данных, содержащую такую ​​же ссылку на $list[0]{one}, как ив $list[0]{two}.
  4. Это достигается путем вывода структуры данных, в которой один элемент содержит ссылку на другой элемент той же структуры.
  5. Но на самом деле это не циклическая ссылка.
1 голос
/ 02 апреля 2011

Я предполагаю, что основная причина в том, что предварительно скомпилированные регулярные выражения на самом деле являются ссылками, а ссылки внутри одной структуры списка уплотняются как оптимизация (\ $ scalar ведет себя так же).Я не совсем вижу полезности этого (предположительно, ссылка на ссылку имеет тот же объем памяти), но, возможно, есть причина, основанная на внутреннем представлении

Причина в том, что она можетбыть ссылкой на структуру данных, которая где-то вложена и содержит ссылку на верхний уровень (цикл).Если бы он продолжал в такую ​​структуру, то он создал бы бесконечный цикл.Чтобы избежать этого, никогда не возвращайтесь к уже увиденной ссылке, поэтому вместо этого он печатает, что уже видел ее, и отсылает вас к предыдущему напечатанному местоположению.

В этом случае петли нет, ноData :: Dumper не может знать, что до того, как он вернется в структуру, в этот момент уже слишком поздно.

Для такого скаляра это, вероятно, необязательно, но, вероятно, это происходит потому, что Data :: Dumperпроверяет, видел ли он уже ссылку, прежде чем проверять тип.Это также дает преимущество, так как показывает, что это ссылка на те же данные, а не их копия, что, возможно, является полезной информацией, которая была бы потеряна, если бы она просто напечатала значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...