在对answer to a question about hash slices的评论中,有人想知道如何使用箭头语法通过哈希引用访问哈希切片,可能会想到
@$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
的值,程序是否正常终止?
答案 0 :(得分:8)
它无效(或至少没有意义)Perl语法 - 我有点意外,它没有被标记为语法错误。
我首先想到它正在尝试在标量上下文中评估数组@$foo
并将结果用作哈希引用,但这似乎并不是正在发生的事情。
相反,从您发布的调试输出,它看起来更像是尝试直接使用内部数组变量(AV)结构作为散列引用(RV),这是一种标量(SV;请参阅perlguts for详情)。
我没有查看源代码,但看起来好像rv2hv
例程注意到它被赋予了错误的结构类型并返回null,或者只是尝试将AV用作RV并且达到同样的效果。 (对不起,如果这听起来有点混乱,那么自从我上次看到perl的内部结构已经有好几年了。)
您可能需要考虑提交错误报告。
BTW,一个更简单的测试案例,证明效果只是@foo->{bar}
。
答案 1 :(得分:5)
@$ref->{@keys}
装置
scalar(@$ref)->{@keys}
所以它应该等同于
my $ref2 = @$ref;
$ref2->{@keys}
不是,所以这是一个错误。它仍然存在于Perl 5.16.0的近期状态。 (v5.15.4,具体而言)
请使用perlbug
命令行工具进行报告。 (只需输入perlbug
并回答几个简单的问题。)