I agree with all points. But the basic question remains: Why should I shift instead of doing a list assignment or a sequence of scalar assignments?
Since I do shifting, I'll explain why I do it.
There are three may ways you can handle parameters to a subroutine:
Method 1: List Assignment
sub foo {
my ( $user, $date, $system ) = @_; # No shifting, and @_ preserved
Method 2: Individual Assignment from @_
sub foo {
my $user = $_[1];
my $date = $_[2]; # Must be YYYY-MM-DD
my $system = $_[3]; # Optional
Method 3: Using "shift"
sub foo {
my $user = shift;
my $date = shift; # Must be YYYY-MM-DD
my $system = shift; # Optional
Method 1 is popular. Ikegami uses it, and so do many other advanced Perl developers. It gives you a parameter list and gives you a way of saying these are my parameters and no others.
However, Method 2 and Method 3 give you a nice, easy to read parameter list, and you can add comments to the end of the line. However, Method 2 also has the advantage of maintaining the value of @_
, so why use shift
?
Take a look at Method 2 again. See a problem? I started with @_[1]
and not with @_[0]
-- a common error. Plus, as you're developing your subroutine, you might decide to reorder your parameters. Using Method 2 means renumbering them. Method 3 doesn't require renumbering, so you don't end up with this:
sub foo {
my $date = $_[1]; # Must be YYYY-MM-DD
my $user = $_[0];
my $system = $_[2]; # Optional
Um, what's the order of the parameters again?
So, what about preserving the value of @_
? If you write a program where you change the value of a parameter, you're probably aren't going to be restoring it from @_
. And, if you do, you are likely to produce some error prone code. If you need to munge a parameter, put it in another variable and munge that. This isn't 1975 where computers had only 4 kilobytes of memory.
And, talking about the 1970s, computers are fast enough that the amount of time of a few (dozen, hundred, thousands) shift operations isn't going to make that much difference in your total runtime. If your program is inefficient, optimize it where it is inefficient, and not by possibly shaving a few milliseconds eliminating a shift. More time will be spent maintaining your program than actually running it.
Damian Conway (The author of Perl Best Practices) recommends both Method #1 and Method #3. He states that Method #1 is "...is more concise, and it keeps the parameters together in a horizontal list, which enhances readability, provided that the number of parameters is small." (the emphasis is mine).
Damian states about Method #3: "The shift-based version is preferable, though, whenever one or more arguments has to be sanity-checked or needs to be documented with a trailing comment."
I simply use Method #3 all of the time. This way, I don't have to worry about reformatting if my parameter list grows, and I simply think it looks better.