I've got two problems with the whole thing that would prevent me from ever accepting it as a "common idiom".

First, the function has a side effect: It modifies its parameters. I understand, that's its primary purpose: to modify its parameters. But this isn't C++; Perl makes it so easy to pass complex return values that idiomatically, it's rare to see a Perl subroutine that intentionally modifies its parameter list (unlike C++, where it's a common idiom to pass objects by reference and manipulate them so that the side effect propagates back through the parameter list). This is why PBP encourages unpacking @_, not just because it looks prettier inside the subroutine, but because it reduces the potential of surprising someone who wasn't watching out for parameter side effects. Writing a Perl subroutine that modifies its parameters violates the principle of least surprise.

Second, as long as we're working so hard to modify the parameter list, let's make the following a fatal error:

swap( qw(this that) );

The first two versions don't throw an error when swap is called with static parameters. The third one does.

But they all have a return value of the swapped list, so they're useful even when modifying the parameter list isn't the goal, right? Well, sort of. All three swap functions produce a reasonable return value. As soon as you decide it's Ok to use the subroutine for its return value instead, and write something like this:

Not only would this idiom need a #comment whenever the subroutine is defined, it would need a comment whenever it's used reminding the reader that in one case we're intentionally modifying the parameters, or in another case we shouldn't use the parameters ever again because they just got modified even though we're capturing a return value.

Regardless of whether or not you happen to be Ok with subroutines that modify their parameter list, one that does it through an extra layer of indirection is even sneakier, and one layer harder to skim as someone reads through the code later on. Though I don't like any of them, at least the last one will throw an error if you attempt to swap literals, and at first glance looks like it does exactly what it does: It acts upon @_, which is an alias. If we ignore the advice of avoiding the pitfall of modifying the parameters, I believe it's a particularly bad practice to follow the PBP suggestion of unpacking the parameter list. It lulls the casual reader into a sense of false security. If PBP had a rule that permitted modifying the parameter list, it would (or should) say to do so in a visually unambiguous way.

(Think how many times we see this in a newbie's code: while( my line = <DATA> ) { my $result = chomp $line; ... } )

Can't say much about the literals and the missing error, I think swapping literals doesn't make much sense ... (well maybe in LISP).

Anyway much of your reasoning is about manipulating arguments is bad practice.

Actually perl has plenty of bultins which do that and many lamda-patterns use this feature (i.e. map/grep {BLOCK} like commands where at least $_ is aliased) and if you look closely into perl6-signature you will find the attribute "rw" for exactly this purpose.

So I can understand if manipulating aliases is not OK for _your_ coding practice, but perl is a multi-paradigm language, where other want to implement their own patters.

For me using two $-sigils like in "$$a" is indication enough that this is no normal assignment, and certainly better to read and more obvious than spreading $_[n] around a 50 line long sub.

update:

I can show you old CORE modules which are programmed w/o unpacking variables and are very hard to maintain. Automatically refactoring $_[n] into $$name would instantly work, even on LHS of assignments and improve readability.

When I first /msg'ed you to inquire whether you saw any differences, I at the time didn't either, and it wasn't until I investigated further that I realized there should be a fatal runtime error (and there is) with the non-unpacked version.

Anyway, you present good arguments, but I am stubborn against considering it a new Perl idiom that should find its way into real code. I do like Moritz's "use perl6" version, because of how explicit it is, but still have concerns. :)