我应该使用$ _ [0]还是复制Perl中的参数列表?

时间:2009-11-18 18:02:48

标签: perl hash

如果我将哈希传递给子:

parse(\%data);

我应该首先使用变量$_[0],还是可以在我想从散列中获取元素时继续访问$_[0]?澄清:

sub parse
{    $var1 = $_[0]->{'elem1'};
     $var2 = $_[0]->{'elem2'};
     $var3 = $_[0]->{'elem3'};
     $var4 = $_[0]->{'elem4'};
     $var5 = $_[0]->{'elem5'};
}
# Versus
sub parse
{    my $hr = $_[0];
     $var1 = $hr->{'elem1'};
     $var2 = $hr->{'elem2'};
     $var3 = $hr->{'elem3'};
     $var4 = $hr->{'elem4'};
     $var5 = $hr->{'elem5'};
}

第二个版本是否更正确,因为它不必继续访问参数数组,或者Perl最终是否以相同的方式将它们互相干扰?

6 个答案:

答案 0 :(得分:11)

在这种情况下没有区别,因为您正在传递对哈希的引用。但是在传递标量的情况下会有区别:

sub rtrim {
    ## remove tailing spaces from first argument
    $_[0] =~ s/\s+$//;
}
rtrim($str); ## value of the variable will be changed

sub rtrim_bugged {
    my $str = $_[0]; ## this makes a copy of variable
    $str =~ s/\s+$//;
}
rtrim($str); ## value of the variable will stay the same

如果您要传递哈希引用,则只创建引用副本。但哈希本身也是一样的。因此,如果您关心代码可读性,那么我建议您为所有参数创建一个变量。例如:

sub parse {
     ## you can easily add new parameters to this function
     my ($hr) = @_; 

     my $var1 = $hr->{'elem1'};
     my $var2 = $hr->{'elem2'};
     my $var3 = $hr->{'elem3'};
     my $var4 = $hr->{'elem4'};
     my $var5 = $hr->{'elem5'};
}

更多描述性变量名称也会改善您的代码。

答案 1 :(得分:7)

有关shift与直接访问@_的效率的一般性讨论,请参阅:

至于您的特定代码,我使用shift,但使用哈希切片简化数据提取:

sub parse
{
    my $hr = shift;
    my ($var1, $var2, $var3, $var4, $var5) = @{$hr}{qw(elem1 elem2 elem3 elem4 elem5)};
}

我会假设这个方法对这些变量做了其他事情,这使得将它们保存在单独的变量中是值得的(也许哈希是只读的,你需要在将它们插入到其他数据之前进行一些修改? ) - 否则为什么不将它们留在它们开始的hashref中?

答案 2 :(得分:5)

你是微观优化;尽量避免这种情况。选择最易读/可维护的内容。通常这将是您使用词法变量的那个,因为它的名称表示其目的......但如果您使用$data$x之类的名称,这显然不适用。

就技术细节而言,在大多数情况下,您可以通过计算perl将使用的基本操作数来估算所花费的时间。对于你的$_[0],非词法数组变量中的元素查找需要多个操作:一个用于获取glob,一个用于获取glob的数组部分,一个用于获取索引(仅一个用于获取常数),一个查找元素。另一方面,$hr是单一操作。为了迎合@_的直接用户,有一个优化可以将$_[0]的操作减少到单个组合操作(当索引介于0和255之间时),但是在你的情况下不会使用它,因为hash-deref context需要在数组元素查找上添加一个标志(以支持自动生成),并且优化的op不支持该标志。

总而言之,使用词汇将更具可读性(如果你不止一次地使用它),在不知不觉中更快。

答案 3 :(得分:4)

我的规则是我尽量不在长于几个语句的子例程中使用$_[0]。之后,所有内容都会获得用户定义的变量。

为什么要将所有哈希值复制到变量中?只需将它们留在它们所属的哈希值中即可。这比你正在考虑的更优化。

答案 4 :(得分:0)

虽然第二个更清楚,但它是一样的

答案 5 :(得分:0)

由于它们都有效,两者都很好,通常的做法是shift关闭参数。

sub parse { my $hr = shift; my $var1 = $hr->{'elem1'}; }