【问题标题】: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 创建了该元素,无论该元素是否被分配。) 整个数组 @ 删除了该别名,并且不 更新任何参数。

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

      【讨论】:

        猜你喜欢
        • 2012-08-09
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-19
        • 2013-06-08
        • 1970-01-01
        • 2021-03-09
        相关资源
        最近更新 更多