Почему ссылки уплотнены в списках Perl?

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

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.

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

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

5
задан Arkadiy Kukarkin 17 June 2010 в 23:25
поделиться

2 ответа

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

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

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

9
ответ дан 18 December 2019 в 10:42
поделиться

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

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

Похожие вопросы: