Arrays

shift#

Remove and return the first element of an array.

shift mutates its argument: it removes the element at index 0, shifts every remaining element down by one position, and returns the removed value. The array shrinks by one. If the array is empty, nothing is removed and undef is returned.

Synopsis#

shift @arr
shift @$aref
shift                   # @_ inside a sub, @ARGV outside

What you get back#

The scalar that used to be at index 0, or undef if the array was empty. Because undef is also a legal array element, a bare undef return does not by itself mean the array was empty — use scalar @arr or a prior defined check when the distinction matters:

my @arr  = (undef, 'two');
my $item = shift @arr;      # undef — but @arr was not empty

Default array: @ARGV vs @_#

Called without an argument, shift picks its array from the surrounding context:

  • Inside a named or anonymous subroutine — @_. This is the idiomatic way to consume positional arguments one at a time.

  • Outside any sub (including in the file scope of a script, and in eval STRING, BEGIN, INIT, CHECK, UNITCHECK, END blocks) — @ARGV. This is how top-of-script argument consumption is usually written.

The choice is made at compile time based on lexical position, not at runtime. A shift inside a sub always targets @_ even if the sub is called from file scope.

Examples#

Consume a single positional argument inside a method. This is the canonical first line of almost every Perl OO method:

sub greet {
    my $self = shift;
    my $name = shift;
    return "hello, $name, from $self";
}

The same method written with a list-unpack @_ slice. Both forms are idiomatic; shift wins when you want to peel off the invocant before deciding what to do with the rest of @_:

sub greet {
    my ($self, $name) = @_;
    return "hello, $name, from $self";
}

Consume @ARGV at the top of a script, one argument at a time:

my $mode = shift // 'default';       # first CLI arg, or 'default'
my $path = shift // die "need a path\n";
# @ARGV now holds whatever is left

A FIFO queue: push on the tail, shift off the head:

my @queue;
push @queue, 'a', 'b', 'c';
while (defined(my $job = shift @queue)) {
    handle($job);
}

Dereference an array ref in place — shift works on @$aref exactly as it does on a named array:

my $aref = [10, 20, 30];
my $head = shift @$aref;             # 10, $aref now [20, 30]

Edge cases#

  • Empty array: returns undef and leaves the array untouched. shift on an empty array is not an error.

  • Complexity is O(n): every remaining element is moved down by one slot. For large arrays used as queues this adds up. When FIFO ordering is not required, pop is O(1); when it is, consider a deque-style data structure or a pair of stacks rather than shift-ing a million-element array in a loop.

  • shift with no argument is context-sensitive by lexical position: inside a sub it targets @_, outside it targets @ARGV. Moving a line of code between those scopes silently changes which array it mutates.

  • Tied arrays: shift calls the SHIFT method on the tied object if one is defined; otherwise it falls back to FETCH on element 0, then DELETE, then a sequence of FETCH/STORE pairs to shift the remaining elements down, then STORESIZE. A custom SHIFT handler is almost always worth writing for performance.

  • Array references: shift @$aref and shift @{ $expr } both work. shift $aref (without the @ sigil) was an experimental feature added in Perl 5.14 and removed in 5.24 — it is a syntax error in the Perl version pperl targets.

  • shift is an lvalue-consumer, not an lvalue: you cannot assign to the result of shift to modify the array. Use splice or direct index assignment for that.

  • Return value in list context: shift always returns a single scalar. Assigning its result to a list — my ($x) = shift @arr — works only because the single scalar fills the first list slot; the remaining slots are undef. Use splice to remove multiple elements at once.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • pop — remove and return the last element; O(1), the right choice when FIFO order is not needed

  • push — append to the tail; pairs with shift to form a FIFO queue

  • unshift — prepend to the head; the inverse of shift, and also O(n) for the same reason

  • splice — remove, insert, or replace any contiguous run of elements; the general tool when shift / pop / unshift / push are not enough

  • @ARGV — the default array shift consumes at file scope

  • @_ — the default array shift consumes inside a sub; holds the caller’s argument list