I want to write a Perl subroutine first
which takes a list as an input, returns the first element in the list and removes the first element from the list.
Like this:
@list = (1,2,3);
print first(@list); // 1
print @list; // 23
This is not quite working:
sub first(@) {
return shift @_;
}
What I get is:
print first(@list); // 1
print @list; // 123
The stack variable @_ changes the way I expect it to (first it is (1, 2, 3)
then it is (2, 3)
), but the list I give as an input (@list
) is not changed. I thought the stack variable saves a reference to the variable it refers to.
When I change a list element in the subroutine it also changes something in @list
but not the one I wanted to, but that one + 1. So if I in the subroutine I were to write:
@_[0] = "X";
and after executing the subroutine print @list
, I would get 2X6
.
You need to put a slash in front of the @
prototype to get an array reference, and then modify the reference. If you just use @
you will get a copy of the array @list
in the subroutine (and the array in the parent would therefore not be modified). From http://perldoc.perl.org/perlsub.html#Prototypes:
Unbackslashed prototype characters have special meanings. Any unbackslashed @ or % eats all remaining arguments, and forces list context.
So you could write:
use strict;
use warnings;
sub first (\@) {
my $a = shift;
return shift @$a;
}
my @list = (1,2,3);
print first(@list) . "\n";
print "@list" . "\n";
Output:
1
2 3