Perl 哈希键行为
输出Perl 哈希键行为,perl,autovivification,Perl,Autovivification,输出 perl -Mstrict -wlE 'my %h; say grep 0, $h{poluted}; say keys %h' 及 没有输出 我想知道为什么输出不同?别名 在Perl的循环构造map、grep和for中,$\ucode>变量被别名化到每个当前项。虽然$\uuu可能是只读的,但它始终表示有效的标量值 例如,以下代码失效: perl -Mstrict -wlE 'my %h; say grep 0, my @r= $h{poluted}; say keys %h' 但这是
perl -Mstrict -wlE 'my %h; say grep 0, $h{poluted}; say keys %h'
及
没有输出
我想知道为什么输出不同?别名
在Perl的循环构造map
、grep
和for
中,$\ucode>变量被别名化到每个当前项。虽然$\uuu
可能是只读的,但它始终表示有效的标量值
例如,以下代码失效:
perl -Mstrict -wlE 'my %h; say grep 0, my @r= $h{poluted}; say keys %h'
但这是可行的:
$_ = 1 for 1, 2, 3; # constants are read-only
请注意,指定执行复制,但别名将名称与现有标量相关联
两个undef
值
Perl有两种unde
:
- 标量可以设置为表示
undef
。例如:
my @nums = (1, 2, 3);
$_ = 1 for @nums; # @nums isn't read-only
- 一种特殊的全局唯一标量,表示只读
undef
值,例如,在右值上下文中访问未初始化的数组索引时返回。在Perl API中,这是&PL\u sv\u unde
。您可以获取对此值的引用,例如\unde
,并可以为其别名变量
访问散列值的两种方法
在内部,通过hv\u fetch
或hv\u fetch\u ent
获取散列项。作为参数,两者都使用散列、密钥和标志,告诉它们访问是否为只读
如果这是只读访问且元素不存在,将返回一个空指针,它在Perl空间中显示为unde
值。此undef
值未连接到哈希。因此,不存在$hash{foo}
意味着未定义$hash{foo}
但如果它不是只读的,并且元素不存在,则会创建一个新条目,然后返回该条目。但是,在通过赋值将该条目设置为另一个值之前,该条目最初是未定义的
那么,为什么问题中的代码不能按预期工作呢?
循环构造的参数列表的别名为$\uu
。如果列表中的表达式是常量或子例程,则不会发生任何异常。但当它们是可变访问时,则意味着读写访问
因此,为了获得$h{policted}
的值,Perl显然以读写模式进行访问。如果我们看一下这个表达式的操作码,我们实际上看到:
grep 0, $h{polluted}
3个推码
4 gv[*h]s
5 rv2hv sKR/1
6常数[PV“污染”]s/裸
7直升机sKM/2#a[t2]vK
常数[IV 0]s
转到9
M
代表MOD
,表示左值/读写访问
为什么这种行为“有意义”
在for
-循环中,将$作为当前元素的别名非常有用。在map
和grep
中,这是一种避免复制整个标量的性能攻击。别名要便宜得多,因为这只意味着一个指针的副本。对于好奇的人来说,可能值得一提的是,可以通过运行类似于$perl-MO=concrete,-exec-E…
的操作码来获得。pod页面中的语法文档我仍然不清楚为什么grep
总是访问它的参数r/w。用户定义的子例程并非如此,请参见:perl-le'sub mod{$\[0]=“modified”}sub nomod{$\[0]}sub refd:lvalue{$\[0]}mod($h{created});nomod({h})$v=refd($h{roref});refd($h{rwref})=1;打印键(%h)
它打印:created\nrwref
@user2719058在所有这些情况下,散列作为helem sKM/LVDEFER,2
访问。我不知道这意味着什么,但它似乎是另一个Performance Hack.tnx,因此grep 0,@[$h{poluted}]}
应该用来防止散列污染。@amon好吧,我想它可以让Perl检测参数别名是否被子例程修改,并推断子例程是否提供左值上下文。我仍然想知道为什么这不适用于grep
。
my $foo; # is this kind of undef
$foo = 1; # isn't undef any more
grep 0, $h{polluted}
3 <0> pushmark s
4 <#> gv[*h] s
5 <1> rv2hv sKR/1
6 <$> const[PV "polluted"] s/BARE
7 <2> helem sKM/2 # <-- hash element access, "M" flag is set!
8 <@> grepstart K
9 <|> grepwhile(other->a)[t2] vK
a <$> const[IV 0] s
goto 9