Perl:使用子例程的splice()数组

时间:2012-03-06 19:30:21

标签: arrays perl subroutine

我需要一个完全删除数组元素的子程序。以下代码失败:

sub del
{
    splice(@_,2,1);
}

@array=(0..5);
print "@array"."\n";
del(@array);
print "@array"."\n";

再次打印相同的阵列,即该元素尚未被删除。 但是,如果我在程序主体中使用splice()而不是调用子程序,它就可以工作。

2 个答案:

答案 0 :(得分:14)

虽然@_的标量元素是传入的数据的别名,但@_本身是一个不同的变量。这意味着$_[1] = "foo"将改变$_[1],但push @_, "foo"不会改变@_。否则my $self = shift将是一件坏事。

您需要传入数组作为参考。

sub del {
    my $array_ref = shift;

    splice @$array_ref, 2, 1;

    return;
}

del \@array;

如果你绝对必须保留del @array界面,这是少数几个适合使用原型的地方之一。

sub del(\@) {
    my $array_ref = shift;

    splice @$array_ref, 2, 1;

    return;
}

del @array;

\@原型告诉Perl通过引用传入@array。我建议反对这样做有两个原因。首先,原型有一堆警告,这使他们不值得麻烦。

更重要的是,del将修改其参数是不明显的。通常,用户定义的Perl函数会复制其参数,因此您可以查看foo @array,并确保@array不会更改foo。这使得人们可以快速浏览代码以处理将影响变量的事物。参考原型将其抛出窗口。现在必须检查每个函数是否存在可能隐藏的引用传递。

答案 1 :(得分:1)

答案可以在perldoc perlsub找到:

  

传入的任何参数都显示在数组@ 中。因此,如果你   调用带有两个参数的函数,它们将存储在$ [0]中   和$ [1]。数组@ 是一个本地数组,          但它的元素是实际标量参数的别名。特别是,如果元素$ [0]更新,则相应   参数更新(如果不是,则发生错误          可更新)。如果参数是调用函数时不存在的数组或哈希元素,则创建该元素   只有在(和如果)它被修改或引用时          它被采取了。 (Perl的某些早期版本创建了元素,无论元素是否已分配给。)分配给   整个数组@ 删除了该别名,但没有          更新任何参数。

简而言之,如果您需要在sub之外显示更改,则可以修改单个元素,但不能修改列表本身。但你可能会返回@_,这将返回修改后的列表,然后你需要将其作为返回值捕获。