I'm frequently using shift
to unpack function parameters:
sub my_sub {
my $self = shift;
my $params = shift;
....
}
However, many on my colleagues are preaching that shift
is actually evil. Could you explain why I should prefer
sub my_sub {
my ($self, $params) = @_;
....
}
to shift
?
The use of shift
to unpack arguments is not evil. It's a common convention and may be the fastest way to process arguments (depending on how many there are and how they're passed). Here's one example of a somewhat common scenario where that's the case: a simple accessor.
use Benchmark qw(cmpthese);
sub Foo::x_shift { shift->{'a'} }
sub Foo::x_ref { $_[0]->{'a'} }
sub Foo::x_copy { my $s = $_[0]; $s->{'a'} }
our $o = bless {a => 123}, 'Foo';
cmpthese(-2, { x_shift => sub { $o->x_shift },
x_ref => sub { $o->x_ref },
x_copy => sub { $o->x_copy }, });
The results on perl 5.8.8 on my machine:
Rate x_copy x_ref x_shift
x_copy 772761/s -- -12% -19%
x_ref 877709/s 14% -- -8%
x_shift 949792/s 23% 8% --
Not dramatic, but there it is. Always test your scenario on your version of perl on your target hardware to find out for sure.
shift
is also useful in cases where you want to shift off the invocant and then call a SUPER::
method, passing the remaining @_
as-is.
sub my_method
{
my $self = shift;
...
return $self->SUPER::my_method(@_);
}
If I had a very long series of my $foo = shift;
operations at the top of a function, however, I might consider using a mass copy from @_
instead. But in general, if you have a function or method that takes more than a handful of arguments, using named parameters (i.e., catching all of @_
in a %args
hash or expecting a single hash reference argument) is a much better approach.