Perl: splice () array using subroutine

I need a subroutine that completely removes an array element in place. The following code failed to execute:

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

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

      

The same array is printed again, i.e. the item is not removed. However, if I use splice()

the main part of the program instead of calling a subroutine, it works.

+3


source to share


2 answers


While scalar elements @_

are flattened to the data that is being passed, @_

it is a different variable in itself. This means it $_[1] = "foo"

will $_[1]

, but push @_, "foo"

not change @_

. Otherwise, there my $self = shift

will be a Bad Thing.

You need to pass the array as a reference.

sub del {
    my $array_ref = shift;

    splice @$array_ref, 2, 1;

    return;
}

del \@array;

      

If you absolutely must maintain an interface del @array

, this is one of the few places where it makes sense to use a prototype.



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

    splice @$array_ref, 2, 1;

    return;
}

del @array;

      

The prototype \@

tells Perl to pass in @array

by reference. I would recommend against doing this for two reasons. First, prototypes have a bunch of caveats that make them not worth the trouble.

More importantly, it makes it not obvious that they del

will change their arguments. Typically Perl UDFs copy their arguments, so you can look foo @array

and be pretty sure @array

it won't be changed to foo

. This allows you to quickly copy code for things that will affect the variable. The reference prototype displays this window. Now each function must be examined for possible hidden pass by reference.

+14


source


The answer can be found with perldoc perlsub

:

Any passed arguments appear in the @ array. Therefore, if you are called a function with two arguments, that will be stored in $ [0] and $ [1]. Array @ is a local array, but its elements are aliases for real scalar parameters. In particular, if the $ [0] element is updated, the corresponding argument is updated (or an error is raised if it is not updatable). If the argument is an array or hash element that did not exist when the function was called, that element is only created when (and if) it is changed or referenced. (Some earlier versions of Perl created an element regardless of whether or not the element is assigned.) Purpose An integer array @ removes this alias and does not update any arguments.



In short, individual items can be changed, but not the lists themselves if you need the changes to appear outside of the sub. But you could probably return @_, which would return the modified list, which you would then need to write as the return value.

+1


source







All Articles