在Perl中,$#array代表什么意思?

21

我在查看以下代码片段:

my @ret = <someMethod>
return (undef) if( $DB_ERROR );
return (undef) unless ($#ret >= 0);

$# 只返回数组中元素的数量吗?


1
我在标题中将$#更改为$#array。你应该意识到$#本身是一个神奇的变量(尽管我认为它在Perl 5.10中被删除了)。 - Leon Timmermans
6
另外,我想指出你的脚本可能存在一个bug。你不应该返回(undef),而是应该简单地说“return”。在列表上下文中,你的函数将被评估为true! - Leon Timmermans
4个回答

45

$#arrayname可以得到最后一个元素的索引,所以如果数组@ret有两个元素,则$#ret为1。

并且,正如Barry Brown所指出的那样,空数组返回-1。

要获取长度,可以在标量上下文中使用数组:

print scalar @ret;

另外,如果@ret里面没有任何内容,$#ret将返回-1。 - Barry Brown

25

edg是正确的,但原始代码过于晦涩。在大多数情况下,$#foo是一个警示标志,说明代码可以更简单地使用scalar @foo

return (undef) unless ($#ret >= 0);

除非foo大于等于bar,否则很难理解。首先将其转化为肯定语句。
return (undef) if ($#ret < 0);

当$#ret < 0时是什么意思?当它为-1时。一个$#ret等于-1的数组长度为0。因此,上述内容可以更简单地写成...

return (undef) if scalar @ret <= 0;

但是你无法拥有一个负长度的数组,所以...
return (undef) if scalar @ret == 0;

在标量上下文中,"scalar" 是多余的,因此 "==" 可以使用。
return (undef) if @ret == 0;

但这只是说“如果@ret为false”的冗长表达方式。
return (undef) if !@ret;

我认为对于简单的语句修饰,使用unless更好表达。
return (undef) unless @ret;

这样不是更容易理解吗?

最后需要注意的是,return undef不被推荐使用,因为在列表上下文中它会做出错误的操作。你会得到一个包含一个undef元素的列表,该元素为真。相反,只需使用空返回,在标量上下文中返回undef,在列表上下文中返回空列表。

return unless @ret;

2
而 $#foo 不是一个红旗的地方之一就是在数组切片中...我的 @five_to_end = @foo[ 5 .. $#foo ]; - draegtun
回复:“不建议使用return undef”。在某些情况下,即使在列表上下文中,您确实希望返回明确的“undef”。这取决于函数通常的使用方式。并不是说您不应该使用“return undef”,而是您不应该在没有思考“为什么我要在这里使用return undef?”的情况下使用它。如果您有一个好的答案,那么就去做吧。 - cjm
1
$#foo不是代码的红旗。 不,它不是。两者有不同的用途。@foo是元素的计数,而$#foo是最后一个索引。如果您正在运行for-index循环,则应使用$#foo。与draegtun提到的数组切片相同。对于OP提出的用例,@foo更准确,因为语句只是检查元素的非零计数。 - SineSwiper
1
@BrendanByrd 是的,它们确实有不同的用途。$#foo 有其用处,但在大多数情况下它们表明代码可能更简单。完整的三部分循环本身就是一个警示标志,以及按索引迭代。for my $idx (0..$#foo) 有其用处,但通常可以更好地编写为 for my $thing (@foo) - Schwern
1
@BrendanByrd 为了澄清,红旗表示需要加强审查的事项;而不是被禁止的事项。我发现很多新手(以及许多教程)在应该使用@foo时使用$#foo非常普遍。 - Schwern

6

请注意,当数组元素为零时,$#array表达式将返回-1。


2
总结其他人的意见,如果按照以下方式编写代码,它会更易读:

my @ret = someMethod();
return if $DB_ERROR;
return unless @ret;

1
这在语义上是不同的。在列表上下文中,return;return undef;的行为是不同的(分别返回一个空列表和包含undef的单元素列表)。 - melpomene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接