我试图解开一些旧代码,其中对$ value进行的操作要是它的大小大于x(其中x是硬编码的int)。这是当前的样子:
if (scalar(@{$value}) > x) {
...
}
与所有旧版代码一样,该$ value几乎可以是任何值(哈希,标量,数组),尽管它应该是不同对象的数组。该代码当前失败,大约有5%的时间出现“不是ARRAY引用”,我试图找出可能破坏它的$ value是什么。
我假设如果$ value未定义,它可能会失败,所以我甚至给了它||。 []但无济于事(相同的错误):
if (scalar(@{$value || []}) > x) {
...
}
我还试图弄清楚为什么我需要@ {}?我的理解是,它在列表上下文中评估$ value,以便标量以后可以确保我得到大小。这会使代码更健壮,还是可以直接使用标量$ value? @ {}甚至可以按照我的想法做吗?
我正在使用perl 5.8。
答案 0 :(得分:2)
您在那里有两个问题。我将分别回答:
@{}
在做什么?在编写@{$thing}
时,您正在取消引用 $thing
到数组中。如您所见,这仅在$thing
是数组引用时才有效。 (其他取消引用运算符是%{$thing}
用于哈希引用,${$thing}
用于标量引用。)
您要做在那里需要解引用运算符。考虑一下:
my $arrayref = [ 'Alice', 'Bob', 'Charlie' ];
my $hashref = { x => 4, y => 5 };
my $string = "Hello, world";
for my $thing ($arrayref, $hashref, $string) {
print "thing --> ", $thing, "\n";
print "scalar(thing) --> ", scalar($thing), "\n";
}
输出:
thing --> ARRAY(0x7f3b8054e468)
scalar(thing) --> ARRAY(0x7f3b8054e468)
thing --> HASH(0x7f3b80560678)
scalar(thing) --> HASH(0x7f3b80560678)
thing --> Hello, world
scalar(thing) --> Hello, world
强制$thing
到标量上下文没有意义。 已经是标量了!
如果您不知道$thing
中包含哪种参考,可以使用Ref::Util
进行检查:
use Ref::Util qw( is_arrayref is_hashref );
for my $thing ($arrayref, $hashref, $string) {
if (is_arrayref($thing)) {
print "array: thing --> ", @{$thing}, "\n";
print "array: scalar(thing) --> ", scalar(@{$thing}), "\n";
}
elsif (is_hashref($thing)) {
print "hash: thing --> ", %{$thing}, "\n";
print "hash: scalar(thing) --> ", scalar(%{$thing}), "\n";
}
else
{
print "else: thing --> ", $thing, "\n";
}
}
输出:
array: thing --> AliceBobCharlie
array: scalar(thing) --> 3
hash: thing --> y5x4
hash: scalar(thing) --> 2/8
else: thing --> Hello, world
观察:
print
输出不带分隔符的每个元素:AliceBobCharlie
3
print
输出没有分隔符的每一对:y5x4
答案 1 :(得分:1)
以下代码将解决:
if ($value and ref $value eq 'ARRAY' and @$value > x) { ... }
基本上,只有当它是ARRAY参考时,才可以取消引用ARRAY。因此必须确保它是ARRAY引用,这样它才不会因HASH等而失败