You need to understand what shift does.
The shift
/unshift
pair of commands are parallel to the pop
/push
pair of commands. All of these commands operate on arrays. By default, shift
(and only shift
) assumes the @_
array when called in a subroutine and @ARGV
when called in the main program. This means the following two statements are identical in a subroutine:
my $foo = shift @_; # Explicit Argument
my $foo = shift # Implicit Argument
Perl's parameter passing is an interesting concept because it doesn't really do named parameter passing like almost all other programs. Instead, everything is passed as one long list of scalars. This makes it hard when you aren't passing in a scalar.
It works okay if I am only passing in a single hash or array:
munge_hash ( %foo );
sub munge_hash {
my %hash = @_;
...
}
And, you have to be careful if you're passing in multiple arguments and an array. In this case, the array must be the last in your list of arguments:
my $foo = "floop";
my $bar = "bloop";
my @array = qw(loop coop soop);
munge_this ( $foo, $bar, @array );
sub munge_this {
say join ":", @_; # Prints "floop:bloop:loop:coop:soop"
my $var1 = shift # floop
my $var2 = shift # bloop
my @arry = @_ # The rest is the array passed.
However, things really fall apart if you're passing in multiple arrays or hashes. All of the elements get merged into a single list of scalars represented by @_
.
munge_two_arrays ( @foo, @bar );
sub munge_two_arrays {
# Problem! Elements of both arrays are in @_.
# How do I separate them out?
}
Thus, it is common not to pass in a whole array, but an array reference:
munge_two_arrays( \@foo, \@bar ); # These are array references
sub munge_two_arrays {
my $array1_ref = shift;
my $array2_ref = shift;
my @array1 = @{ $array1_ref } # Dereference array references to make arrays
my @array2 = @{ $array2_ref } # Dereference array references to make arrays
}
This keeps the values of the two arrays from getting merged into a single @_
.