我需要在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是如何工作的。在这段代码中,我没有看到\%hash值被重置,并且看起来每个循环都会重置$ p(这是一个局部变量)。我甚至可以用数据转储器看到它: 运行:
#!/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)
取消注释该行清除显示$ p每次都是一个新变量。
如果每次重置$ p,如何构建\%hash?
答案 0 :(得分:5)
$p
每次都没有“重置”;它被设置为哈希中的下一个较低级别,刚刚添加。此时它只是一个空的hashref {}
,因为它将在下一个循环迭代中填充。
我不确定你是如何得出结论$p
每次都是一个新变量,但这是不正确的......它只是指向%hash
结构中的新位置。由于它是在循环之外声明的,因此循环迭代时它不会丢失它的值。
答案 1 :(得分:1)
为$p
引用的哈希添加显式标记:
...
print "AFTER:\n";
$p->{'$p'} = 'is here!';
print Dumper(\%hash);
delete $p->{'$p'};
}
然后最后几个AFTER转储看起来像
AFTER: $VAR1 = { 'a' => { 'b' => { 'c' => { '$p' => 'is here!' } } } }; AFTER: $VAR1 = { 'a' => { 'b' => { 'c' => { 'd' => { '$p' => 'is here!' } } } } };
是的,在每个新深度,$p
引用空哈希,但后退一步以查看%hash
的整体结构。
答案 2 :(得分:1)
想看到一些很酷的东西吗?这也是一样的(只有你从未看到它分配 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,当它像hashref一样被解决时,它会创建hashref。