Subroutines and Ampersands
I’ve had this discussion several times recently, so I thought it was worth writing a blog post so that I have somewhere to point people the next time it comes up.
Using ampersands on subroutine calls (&my_sub or &my_sub(...)) is never necessary and can have potentially surprising side-effects. It should, therefore, never be used and should particularly be avoided in examples aimed at beginners.
Using an ampersand when calling a subroutine has three effects.
- It disambiguates the code so the the Perl compiler knows for sure that it has come across a subroutine call.
- It turns off prototype checking.
- If you use the &my_sub form (i.e. without parentheses) then the current value of @_ is passed on to the called subroutine.
Let’s look at these three effects in a little more detail.
Disambiguating the code is obviously a good idea. But adding the ampersand is not the only way to do it. Adding a pair of parentheses to the end of the call (my_sub()) has exactly the same effect. And, as a bonus, it looks the same as subroutine calls do in pretty much every other programming language ever invented. I can’t think of a single reason why anyone would pick &my_sub over my_sub().
I hope we’re agreed that prototypes are unnecessary in most Perl code (perhaps that needs to be another blog post at some point). Of course there are a few good reasons to use them, but most of us won’t be using them most of the time. If you’re using them, then turning off prototype checking seems to be a bad idea. And if you’re not using them, then it doesn’t matter whether they’re checked or not. There’s no good argument here for using ampersands.
Then we come to the invisible passing of @_ to the called subroutine. I have no idea why anyone ever thought this was a good idea. The perlsub documentation calls it “an efficiency mechanism” but admits that is it one “that new users may wish to avoid”. If you want @_ to be available to the called subroutine then just pass it in explicitly. Your maintenance programmer (and remember, that could be you in six months time) will be grateful and won’t waste hours trying to work out what is going on.
So, no, there is no good reason to use ampersands when calling subroutines. Please don’t use them.
There is, of course, one case where ampersands are still useful when dealing with subroutines – when you are taking a reference to an existing, named subroutine. But that’s the only case that I can think of.
What do you think? Have I missed something?
It’s unfortunate that a lot of the older documentation on CPAN (and, indeed, some popular beginners’ books) still perpetuate this outdated style. It would be great if we could remove it from all example code.
Update: In the comments, a few people question my description of the &my_sub mechanism of passing on @_ to the called subroutine as being pointless. And, yes, they’re right. There are some places where that mechanism is useful. But I think that if you’re at the stage where you’re using tail-recursion, continuations or co-routines then I think you’re quite capable of understanding the limitations of the advice in this article.
I stand by my conclusion that in most cases, &my_sub should be replaced with my_sub().