2

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.

3
  • 1
    Why not use shift to achieve this? Commented Jan 6, 2015 at 10:17
  • That's what I'm doing in the subroutine Commented Jan 6, 2015 at 10:21
  • 2
    But why would you like to write the subroutine? When you could simply use shift? Commented Jan 6, 2015 at 10:32

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

Comments

1

You don't have lists there, you have arrays. Arrays and lists are different in Perl (as this great blog post explains). If you have an array called @list then you're just guaranteed to confuse yourself (and whoever maintains your code in the future).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.