The perils of & (and prototypes too!)
In a recent post, Chris K asks, why do I recommend using
function() rather than
If you didn’t that’s ok, this is a bit of a toughie, and yes I threw in a gratuitous
$" for fun (which is the string used to join a quoted array). For those of you without a terminal handy, the output is:
hello world and good bye! 2 hello world and good bye! hello world hello world good bye!
In my example
mysub enforces scalar context onto its argument. Now prototypes should not be used lightly, and I rarely recommend them, but when they are used, it is often for a good reason. In this case, the prototyped function is probably not what an author writing that function would have meant. (S)he probably meant, ‘this function only takes one argument’, and it kinda worked, but it didn’t.
Anyway, the first lesson is that calling a function with
& works, but it defeats prototypes. In the example the author was probably wrong to use prototypes, but in most cases, as I said, when a prototype is used, it is for a good reason, and defeating them should come with even MORE reason.
I have actually almost used that once, I wanted to make a clever wrapper of List::Util::reduce and to do so I would have had to defeated its prototype. The endeavor failed and so that code did not see the light of day, but it got close. Other than that case, I have never needed to defeat a prototype, and so I have never used
&function() in anger.
&function is more clever and is used in some more common wrappings. It means call the
function() but with my current
@_. This isn’t as useful as its ‘twin’
goto &function which mean, ‘stop this function and instead start doing
function() with my current @_ instead, and remove the current function call from the stack trace’. This is actually useful for function wrapping, say like in an
AUTOLOAD function. Again, though, you do this when you mean to, not all the time. I think I have perhaps used
goto &function a half-dozen times in anger.
The take-away message here is, in Perl 5 you should almost always be using
function (though the bareword is confusing in some cases, especially if you forget strict and warnings!). You should almost never need (and therefore not want to accidentally incur the potential side-effects) of using
&. They won’t happen often, but when you get into the habit of using
& and you do accidentally defeat a useful prototype, or unintentionally pass forward your
@_, it will make for a terrible debugging session.
Anyway, as always, happy Perling!
P.S. I am happy to see that people still find Learn to Spot a Good Tutorial useful, and it reminds me that it will soon need another version and year bump!
P.P.S, the site that hosts that article also contains a list of good tutorials, and some “not so good ones” too, so you can use/recommend them.