Why does this Perl shuffle function not shuffle?

Viewed 82
#!/usr/bin/perl

use Data::Dumper;
use strict;
use List::Util qw(shuffle);

my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
@arr = shuffle @arr;
print Dumper @arr;

Perl version is v5.32.0. The result I see is always Foo Bar Baz Qux Quux Quuz.

$ ~/tmp/shuffle.perl
$VAR1 = [
      'Foo',
      'Bar',
      'Baz',
      'Qux',
      'Quux',
      'Quuz'
    ];
$ /usr/bin/perl --version

This is perl 5, version 32, subversion 0 (v5.32.0) built for x86_64-linux-gnu-thread-multi
2 Answers

my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];

This is an array with a single element, i.e. the element [qw(Foo Bar Baz Qux Quux Quuz)]. There is thus nothing to shuffle here. What you likely want is:

 my @arr = qw(Foo Bar Baz Qux Quux Quuz);

This is your existing code:

use Data::Dumper;
use strict;
use List::Util qw(shuffle);

my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
@arr = shuffle @arr;
print Dumper @arr;

Your array looks like this:

@arr = (
    [qw(Foo Bar Baz Qux Quux Quuz)], # @arr element zero
                                     # @arr element 1 doesn't exist
                                     # @arr element 2 doesn't exist
                                     # etc...
);

In other words, your array contains a single element. That element is a reference to an anonymous array that contains Foo, Bar, Baz, Qux, Quux, Quuz. You created a multi-level data structure.

You have two ways forward. If you really wanted a multi-level data structure, then sorting the elements in the anonymous array referred to by $arr[0] can be shuffled like this:

@{$arr[0]} = shuffle(@{$arr[0]});

If you don't need a multi-level data structure, you should be defining @arr like this:

@arr = qw(.........); # Notice the lack of [ and ]

Then shuffle becomes:

@arr = shuffle(@arr);

The [LIST] syntax constitutes an anonymous array reference constructor. You probably don't need an anonymous array reference.

https://perldoc.perl.org/perlreftut is a good tutorial on Perl references.

https://perldoc.perl.org/perldsc is a good reference on creating Perl data structures.

List::Util's shuffle function is a Fisher Yates Shuffle implementation in Perl XS (essentially, implemented in C). It is heavily used and part of the core Perl distribution, and has been distributed as part of Perl since Perl 5.8, which goes back well over a decade. It's pretty solid and will work just fine.

Related