While the scalar elements of @_ are aliased to the data which is passed in, @_ itself is a different variable. This means $_[1] = "foo" will alter $_[1] but push @_, "foo" will not alter @_. Otherwise my $self = shift would be a Bad Thing.
You need to pass in the array as a reference.
sub del {
my $array_ref = shift;
splice @$array_ref, 2, 1;
return;
}
del \@array;
If you absolutely must keep the del @array interface, this is one of the few places where it's appropriate 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 pile of caveats which make them not worth the trouble.
More importantly, it makes it non-obvious that del will modify its arguments. Normally user defined Perl functions copy their arguments, so you can look at foo @array and be reasonably sure @array will not be altered by foo. This enables one to skim the code quickly for things which will affect a variable. A reference prototype throws this out the window. Now every function must be examined for a possible hidden pass-by-reference.