Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

It's been a while since I've played in Perl but I remember the below shuffle code working. However, on the script I'm working on today says there is an error 'Modification of non-creatable array value attempted, subscript -1). The specific line it is complaining about is @$array$i,$j = @$array$j,$i; Any suggestions on how to fix this?
sub shuffle { my $array = shift; my $i = @$array; while ( --$i ) { my $j = int rand( $i+1 ); @$array[$i,$j] = @$array[$j,$i]; } }
  • Comment on Array shuffle code produces 'Modification of non-creatable array value attempted' error
  • Download Code

Replies are listed 'Best First'.
Re: Array shuffle code produces 'Modification of non-creatable array value attempted' error
by toolic (Bishop) on May 29, 2015 at 18:27 UTC
    Works for me when I pass it a reference to a simple array on Perl version 5.12.2:
    use warnings; use strict; use Data::Dumper; my $arr = [1..5]; shuffle($arr); print Dumper($arr); sub shuffle { my $array = shift; my $i = @$array; while ( --$i ) { my $j = int rand( $i+1 ); @$array[$i,$j] = @$array[$j,$i]; } } __END__ $VAR1 = [ 3, 5, 4, 1, 2 ];

    What version of Perl? How do you call the sub?

    See also List::Util::shuffle

Re: Array shuffle code produces 'Modification of non-creatable array value attempted' error
by Anonymous Monk on May 29, 2015 at 19:42 UTC

    The probable cause is passing an empty array to shuffle:

    shuffle([]);
    Suggested fix:   my $i = @$array || return;

Re: Array shuffle code produces 'Modification of non-creatable array value attempted' error
by stevieb (Canon) on May 29, 2015 at 18:48 UTC

    toolic's code works on Perl 5.18.2 as well.

Re: Array shuffle code produces 'Modification of non-creatable array value attempted' error
by ikegami (Patriarch) on Jun 01, 2015 at 16:45 UTC
    The error occurs when you assign to a negative index so large that it indicates a negative element.
    $ perl -e' @a = qw( abc def ); $a[-1] = "ghi"; $a[-2] = "jkl"; $a[-3] = "mno"; ' Modification of non-creatable array value attempted, subscript -3 at - +e line 4.

    In your code, that will happen when an empty array is passed to shuffle. Fix by changing

    while ( --$i )
    to
    while ( --$i > 0 )