@$ref->{@keys} 试图访问什么?
在有关哈希切片的问题的答案,有人想知道如何使用箭头语法通过哈希引用访问哈希切片,认为也许
@$ref->{@keys}
可以这样做。
是的,正确的语法是 @$ref{@keys}
或 @{$ref}{@keys}
,但这不是这个问题的重点。
我试图计算出带有箭头的表达式所需的数据结构:
#! /usr/bin/env perl
use strict;
use warnings;
my $ref = {"a" => 1, "b" => 2, "c" => 3};
my @keys = qw/ a b c /;
#$ref = [ { a => 9, b => 8, c => 7 } ];
#$ref = [ { a => {}, b => {}, c => {} } ];
print @$ref->{@keys}, "\n";
正如所写,代码失败了
Not an ARRAY reference at ./prog line 12.
这是有道理的: @$ref
想要对数组的引用,所以我尝试包装哈希引用内部对匿名数组的引用。这些尝试失败了,
Can't use an undefined value as a HASH reference at ./prog line 12.
跟踪输出是
$ debugperl -Dt prog [...] (prog:12) pushmark (prog:12) padsv($ref) (prog:12) rv2av (prog:12) rv2hv Can't use an undefined value as a HASH reference at prog line 12.
print
行的语法转储是
$ debugperl -Dx prog [...] { 484 TYPE = print ===> 2 FLAGS = (VOID,KIDS) { 485 TYPE = pushmark ===> 486 FLAGS = (SCALAR) } { 372 TYPE = helem ===> 371 FLAGS = (SCALAR,KIDS) { 487 TYPE = rv2hv ===> 361 TARG = 5 FLAGS = (SCALAR,KIDS,REF) PRIVATE = (STRICT_REFS) { 373 TYPE = rv2av ===> 487 TARG = 4 FLAGS = (SCALAR,KIDS,REF) PRIVATE = (STRICT_REFS) { 486 TYPE = padsv ===> 373 TARG = 1 FLAGS = (SCALAR,MOD) } } } { 361 TYPE = padav ===> 372 TARG = 2 FLAGS = (SCALAR) } } { 371 TYPE = const ===> 484 TARG = 19 FLAGS = (SCALAR) } } [...]
未定义值来自哪里?对于 $ref
的什么值,程序会正常终止?
In a comment on an answer to a question about hash slices, someone wanted to know how to use arrow syntax to access a hash slice through a hash reference, thinking perhaps that
@$ref->{@keys}
would do so.
Yes, the correct syntax is either @$ref{@keys}
or @{$ref}{@keys}
, but that's beside the point of this question.
I tried to work out the data structure that the expression with an arrow requires:
#! /usr/bin/env perl
use strict;
use warnings;
my $ref = {"a" => 1, "b" => 2, "c" => 3};
my @keys = qw/ a b c /;
#$ref = [ { a => 9, b => 8, c => 7 } ];
#$ref = [ { a => {}, b => {}, c => {} } ];
print @$ref->{@keys}, "\n";
As written, the code fails with
Not an ARRAY reference at ./prog line 12.
That makes sense: @$ref
wants a reference to an array, so I tried wrapping hash references inside a reference to an anonymous array. Those attempts failed with
Can't use an undefined value as a HASH reference at ./prog line 12.
The trace output is
$ debugperl -Dt prog [...] (prog:12) pushmark (prog:12) padsv($ref) (prog:12) rv2av (prog:12) rv2hv Can't use an undefined value as a HASH reference at prog line 12.
The syntax dump for the print
line is
$ debugperl -Dx prog [...] { 484 TYPE = print ===> 2 FLAGS = (VOID,KIDS) { 485 TYPE = pushmark ===> 486 FLAGS = (SCALAR) } { 372 TYPE = helem ===> 371 FLAGS = (SCALAR,KIDS) { 487 TYPE = rv2hv ===> 361 TARG = 5 FLAGS = (SCALAR,KIDS,REF) PRIVATE = (STRICT_REFS) { 373 TYPE = rv2av ===> 487 TARG = 4 FLAGS = (SCALAR,KIDS,REF) PRIVATE = (STRICT_REFS) { 486 TYPE = padsv ===> 373 TARG = 1 FLAGS = (SCALAR,MOD) } } } { 361 TYPE = padav ===> 372 TARG = 2 FLAGS = (SCALAR) } } { 371 TYPE = const ===> 484 TARG = 19 FLAGS = (SCALAR) } } [...]
Where is the undefined value coming from? For what values of $ref
does the program terminate normally?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
它不是有效的(或者至少没有意义)Perl 语法——我有点惊讶它没有被标记为语法错误。
我首先认为它试图在标量上下文中评估数组
@$foo
并将结果用作哈希引用,但这似乎并不是正在发生的事情。相反,从您发布的调试输出来看,它看起来更像是尝试直接使用内部数组变量(AV)结构作为哈希引用(RV),这是一种标量(SV;请参阅 perlguts 了解详细信息)。
我没有查看源代码,但看起来 rv2hv 例程要么注意到它被赋予了错误的结构类型并返回 null,要么只是尝试将 AV 用作 RV 并且这样就达到了同样的效果。 (抱歉,如果这听起来有点混乱,自从我上次查看 Perl 的内部结构以来已经有好几年了。)
您可能需要考虑提交错误报告。
顺便说一句,演示效果的更简单的测试用例就是
@foo->{bar}
。It's not valid (or at least not meaningful) Perl syntax — I'm a bit surprised it's not flagged as a syntax error.
I first thought it was trying to evaluate the array
@$foo
in scalar context and use the result as a hash reference, but that doesn't quite seem to be what's going on.Rather, from the debug output you posted, it looks more like it's trying to directly use the internal array variable (AV) structure as a hash reference (RV), which is a type of scalar (SV; see perlguts for details).
I haven't looked at the source, but it looks as if the
rv2hv
routine either notices that it's been given the wrong kind of structure and returns null, or just tries to use the AV as an RV and achieves the same effect that way. (Sorry if that may sound a bit muddled, it's been some years since I last looked at the internals of perl.)You might want to consider submitting a bug report.
BTW, a simpler test case that demonstrates the effect is just
@foo->{bar}
.意味着
so it 应该等同于
It's not,所以这是一个错误。它仍然存在于即将成为 Perl 5.16.0 的近当前状态中。 (具体为 v5.15.4)
请使用
perlbug
命令行工具进行报告。 (只需输入perlbug
并回答几个简单的问题。)means
so it should be equivalent to
It's not, so it's a bug. It's still present in the near-current state of what will become Perl 5.16.0. (v5.15.4, to be specific)
Please report using the
perlbug
command line tool. (Just enterperlbug
and answer a few simple questions.)