Создание структуры справочных данных хеша переменной глубины в perl - PullRequest
3 голосов
/ 21 июля 2010

Мне нужно было построить структуру данных хэша переменной глубины в perl.В конце концов я нашел этот кусок кода:


#!/usr/bin/perl -w
use strict;

my %hash;
my $value = "foo";
my @cats = qw(a b c d);

my $p = \%hash;
foreach my $item (@cats) {
 $p->{$item} = {} unless exists($p->{$item});
 $p = $p->{$item};
}

Мой вопрос: как и почему это работает.Я думал, что знаю, как работает Perl.Ни в одной точке этого кода я не вижу сбрасываемого значения хеша \%, и кажется, что $ p (это локальная переменная) сбрасывается в каждом цикле.Я мог даже увидеть это с помощью дампера данных: Running:


#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my %hash;
my $value = "foo";
my @cats = qw(a b c d);

my $p = \%hash;
foreach my $item (@cats) {
 print "BEFORE:\n";
 print Dumper(\%hash);
 #print Dumper($p);
 $p->{$item} = {} unless exists($p->{$item});
 $p = $p->{$item};
 print "AFTER:\n";
 print Dumper(\%hash);
 #print Dumper($p);
}

И затем раскомментирование строки с

#print Dumper($p)
CLEARLY показывает, что $ p является новой переменной каждый раз.хэш получает сборку, если $ p каждый раз сбрасывается?

Ответы [ 3 ]

5 голосов
/ 21 июля 2010

$p не "сбрасывается" каждый раз; он устанавливается на следующий более низкий уровень в хэше, только что добавленный. На данный момент это просто пустой хеш-адрес, {}, потому что он будет заполнен на следующей итерации цикла.

Я не уверен, как вы пришли к выводу, что $p - это новая переменная каждый раз, но это неверно ... она просто указывает на новое место в структуре %hash. Поскольку он был объявлен вне цикла, он не теряет своего значения при итерации цикла.

1 голос
/ 22 июля 2010

Хотите увидеть что-нибудь классное?Это делает то же самое (только вы никогда не увидите, чтобы он присваивал hashref !)

my $p = \\%hash; # $p is a reference to a hashref
foreach my $item (@cats) {
    # because $p references a reference, you have to dereference
    # it to point to the hash.
    $p = \$$p->{$item} unless exists $$p->{$item};
}

Слот autovivified , как только вы ссылаетесь на него, и когдак нему обращаются, как к хэшрефу, он создает этот хешреф.

1 голос
/ 21 июля 2010

Добавить явный маркер к хешу, к которому относится $p:

 ...
 print "AFTER:\n";
 $p->{'$p'} = 'is here!';
 print Dumper(\%hash);
 delete $p->{'$p'};
}

Тогда последняя пара ПОСЛЕ дампов выглядит как

AFTER:
$VAR1 = {
  'a' => {
    'b' => {
      'c' => {
        '$p' => 'is here!'
      }
    }
  }
};

AFTER:
$VAR1 = {
  'a' => {
    'b' => {
      'c' => {
        'd' => {
          '$p' => 'is here!'
        }
      }
    }
  }
};

Да, на каждой новой глубине $p относится к пустому хешу, но сделайте шаг назад, чтобы увидеть общую структуру %hash.

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