我需要一个完全删除数组元素的子程序。以下代码失败:
sub del
{
splice(@_,2,1);
}
@array=(0..5);
print "@array"."\n";
del(@array);
print "@array"."\n";
再次打印相同的阵列,即该元素尚未被删除。
但是,如果我在程序主体中使用splice()
而不是调用子程序,它就可以工作。
答案 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之外显示更改,则可以修改单个元素,但不能修改列表本身。但你可能会返回@_,这将返回修改后的列表,然后你需要将其作为返回值捕获。