Perl:计算数组大小时不是数组引用
Perl: not an array reference while calculating array size
我正在尝试理清一些遗留代码,其中对 $value 进行操作的前提条件是它的大小大于 x(其中 x 是硬编码的 int)。这是它目前的样子:
if (scalar(@{$value}) > x) {
...
}
与所有遗留代码一样,这个 $value 几乎可以是任何东西(散列、标量、数组),尽管它应该是不同对象的数组。此代码目前在大约 5% 的时间内因 "Not an ARRAY reference" 失败,我正在尝试找出可能破坏它的 $value。
我假设如果 $value 未定义它可能会失败所以我什至给了它一个 || [] 但无济于事(同样的错误):
if (scalar(@{$value || []}) > x) {
...
}
我也在想为什么我需要@{}?我的理解是,它在列表上下文中评估 $value,以便标量稍后可以确保我获得大小。这会使代码更健壮,还是我可以直接使用标量 $value? @{} 会做我想做的事吗?
我正在使用 perl 5.8。
下面的代码将解决:
if ($value and ref $value eq 'ARRAY' and @$value > x) { ... }
基本上,只有当它是 ARRAY 引用时,您才能取消对 ARRAY 的引用。所以确保它是一个 ARRAY ref 是必须的,这样它就不会因为 HASH 等而失败
你有两个问题。我会分开回答:
问题:@{}
在做什么?
当您写入 @{$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
观察:
- arrayref 在取消引用时变成其元素的列表。
print
输出每个没有分隔符的元素:AliceBobCharlie
- arrayref 在取消引用并强制转换为标量时变为元素数:
3
- hashref 在取消引用时变成键和值的列表。
print
输出没有分隔符的每一对:y5x4
- 当取消引用并强制转换为标量时,hashref 会变成 string,其中第一个数字是键的数量,第二个数字是哈希表中桶的数量:
2/8
我正在尝试理清一些遗留代码,其中对 $value 进行操作的前提条件是它的大小大于 x(其中 x 是硬编码的 int)。这是它目前的样子:
if (scalar(@{$value}) > x) {
...
}
与所有遗留代码一样,这个 $value 几乎可以是任何东西(散列、标量、数组),尽管它应该是不同对象的数组。此代码目前在大约 5% 的时间内因 "Not an ARRAY reference" 失败,我正在尝试找出可能破坏它的 $value。
我假设如果 $value 未定义它可能会失败所以我什至给了它一个 || [] 但无济于事(同样的错误):
if (scalar(@{$value || []}) > x) {
...
}
我也在想为什么我需要@{}?我的理解是,它在列表上下文中评估 $value,以便标量稍后可以确保我获得大小。这会使代码更健壮,还是我可以直接使用标量 $value? @{} 会做我想做的事吗?
我正在使用 perl 5.8。
下面的代码将解决:
if ($value and ref $value eq 'ARRAY' and @$value > x) { ... }
基本上,只有当它是 ARRAY 引用时,您才能取消对 ARRAY 的引用。所以确保它是一个 ARRAY ref 是必须的,这样它就不会因为 HASH 等而失败
你有两个问题。我会分开回答:
问题:@{}
在做什么?
当您写入 @{$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
观察:
- arrayref 在取消引用时变成其元素的列表。
print
输出每个没有分隔符的元素:AliceBobCharlie
- arrayref 在取消引用并强制转换为标量时变为元素数:
3
- hashref 在取消引用时变成键和值的列表。
print
输出没有分隔符的每一对:y5x4
- 当取消引用并强制转换为标量时,hashref 会变成 string,其中第一个数字是键的数量,第二个数字是哈希表中桶的数量:
2/8