Search code examples
perlparameter-passingsubroutine

Why shifted value from @_ is not alias?


shift
Shifts the first value of the array off and returns it...

This is done for speed optimization and to avoid copying by value.

Also in perlsub

The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated

Thus if we do my $self = shift in our sub, we shift the first value from @_, which is an alias, is it not?

But when we compare these two:

sub test {
     print \$_[0];    # SCALAR(0xf73c38)
     my $x =  shift;
     print \$x;       # SCALAR(0xf79800)
}

We see that $x is the copy.

Why is the shifted value from @_ not an alias?

So if the value is copied for the case my $x = shift too, what benefit does it provide over my $x = $_[0]?


Solution

  • The shifted value is an alias

    $ perl -E 'sub F{say \$_[0]; say \shift} $x=42; say \$x; F($x)'
    SCALAR(0x1d7f1e0)
    SCALAR(0x1d7f1e0)
    SCALAR(0x1d7f1e0)
    

    The assignment operation (e.g., $x = $_[0] or $x = shift) creates a copy of the scalar on the right hand side, so the newly assigned value is no longer an alias.

    As toolic said, the benefit of shift is to modify @_, which sometimes makes it easier to use in the rest of your subroutine.

    You could still work with a reference to the shifted value if you still wanted to be able to modify the input

    $ perl -E 'sub G { my $x=\shift; $$x = 19 } my $z = 42; G($z); say $z'
    19