【问题标题】:Perl: splice() array using subroutinePerl:使用子例程的 splice() 数组
【发布时间】:2012-03-24 08:00:45
【问题描述】:
我需要一个子程序就地完全删除一个数组元素。以下代码失败:
sub del
{
splice(@_,2,1);
}
@array=(0..5);
print "@array"."\n";
del(@array);
print "@array"."\n";
再次打印相同的数组,即元素尚未被删除。
但是,如果我在程序主体中使用splice() 而不是调用子程序,它就可以工作。
【问题讨论】:
标签:
arrays
perl
subroutine
【解决方案1】:
虽然@_ 的标量元素是传入数据的别名,但@_ 本身是一个不同的变量。这意味着$_[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 更改。这使人们能够快速浏览代码以查找会影响变量的事物。参考原型将其抛出窗外。现在必须检查每个函数是否存在可能的隐藏传递引用。
【解决方案2】:
可以通过perldoc perlsub找到答案:
传入的任何参数都显示在数组@ 中。因此,如果你
调用带有两个参数的函数,这些参数将存储在 $[0]
和 $[1]。数组@ 是一个本地数组,
但它的元素是实际标量参数的别名。特别是,如果元素 $[0] 被更新,相应的
参数已更新(如果未更新,则会发生错误
可更新)。如果参数是调用函数时不存在的数组或哈希元素,则创建该元素
仅当(并且如果)它被修改或引用
它被采取了。 (一些早期版本的 Perl 创建了该元素,无论该元素是否被分配。)
整个数组 @ 删除了该别名,并且不
更新任何参数。
简而言之,可以修改单个元素,但不能修改列表本身,如果您需要更改在子之外可见。但是您可能会返回 @_,这将返回修改后的列表,然后您需要将其捕获为返回值。