ernix ernix - 6 months ago 52
Perl Question

Swap two arrays without using `@tmp`

It is very simple to swap two scalar values like:

($ours, $theirs) = ($theirs, $ours);

Then, how should I do this with array variables?

# (@ours, @theirs) = (@theirs, @ours); # XXX

# lame
my @tmp = @ours;
@ours = @theirs;
@theirs = @tmp;


Perl flattens all lists, and list assignment is greedy, so you can never assign to (@ours, @theirs) and expect @theirs to get anything. To put it another way... You can't pass an 'array' to a subroutine. Subroutines in Perl can only receive a list of 0 or more scalars.

You could swap the individual (scalar) elements of the array inside a loop, but this assumes both arrays are of equal length

for my $i (0 .. $#ours) {
    ( $ours[$i], $theirs[$i] ) = ( $theirs[$i], $ours[$i] );

Perl 5.22 did introduce an experimental feature called reference aliasing which allows you to assign to a reference. If you are running 5.22 or later, you can enable the experimental feature and then do this.

(\@ours, \@theirs) = (\@theirs, \@ours);

To enable the feature, and disable the warnings for using an experimental feature, you would do this

use v5.22;
use warnings;
use feature 'refaliasing';
no warnings 'experimental::refaliasing';

Alternatively, install the experimental module which handles the warnings for you

use v5.22;
use warnings;
use experimental 'refaliasing';