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

Could someone tell me what this means? Im not sure why this isnt working. Heres the error "Modification of a read-only value attempted at line 868 <LIST> line 22". What does the <LIST> line 22 mean? Heres the code:
# Grabs each district from all_store array foreach $dist_only (@all_store_info) { my @array = split(/ / , $dist_only); my $test = @array; next if $test < 2; $distlist = "$array[1] $array[2] $array[3]"; push(@dist_list, $distlist); #print "$distlist\n"; } @dist_list = sort { $a <=> $b } @dist_list; my %uniq; undef @uniq{@dist_list}; @dist_list = keys %uniq;
Thanks, Paul

Replies are listed 'Best First'.
Re: read-only error
by ikegami (Patriarch) on Aug 24, 2006 at 17:56 UTC

    When perl dies/warns with a message that doesn't end in a newline, it displays the file name and the line number where die was called.

    If an I/O read operation has been performed and the handle is still open, perl will also dipslay the name of the handle and the number of lines that have been read from that file handle. (Well, $. really.) This helps debug errors based on inputed data.

    See Playing with "<FH> line 123" die messages.

    Update: As for the "Modification of a read-only value attempted" part, that usually happens when a variable (usually $_) is aliased to a constant, and a value is assigned to that variable. For example,

    sub trim { $_ = $_[0]; # Assigns to $_, but $_ is aliased to " abc ". s/^\s+//g; s/\s+$//g; return $_; } # Fix: # sub trim { # for ($_[0]) { # foreach (unlike while) localizes the loop var. # s/^\s+//g; # s/\s+$//g; # return $_; # } # } print trim($_) for " abc ", " def ", " ghi "

    and

    sub f { my $pos = tell(DATA); while (<DATA>) { # Assigns to $_, but $_ is aliased to 1. print; } seek(DATA, $pos, 0); } # sub f { # my $pos = tell(DATA); # while (defined(my $line = <DATA>)) { # print $line; # } # seek(DATA, $pos, 0); # } f() for 1,2,3; __DATA__ a b c
      Another cause for the Modification of a read-only value error is using a sort block that dereferences $a and $b, and has gaps.

      This is ok:

      use strict; use warnings; my @list; $list[0] = 0; $list[2] = 2; @list = sort {$a <=> $b} @list;
      This isn't:
      use strict; use warnings; my @list; $list[0] = [0]; $list[2] = [2]; @list = sort {$$a[0] <=> $$b[0]} @list;

        $a and $b are read-only in a sort block.

        @list = sort { $a = 1; } @list;

        You're getting the error because you are attempting to auto-vivify them.

        I hate auto-vivification, or at least that it's on by default.

Re: read-only error
by imp (Priest) on Aug 24, 2006 at 17:59 UTC
    It is very difficult to guess what is causing a problem when provided with insufficient context.

    Please provide a working example that demonstrates the problem. Follow these guidelines when writing the example:

    • use strict and warnings
    • The example should be runnable with nothing more than copy+paste
    • Keep the example concise. Cut out any code that is not neccesary to reproduce the error
    Additionally, if you are posting an error message that specifies the line on which the error occurred it would be most helpful to tell us which line in your code is producing the error. Line 868 isn't terribly helpful.
      While using warnings. It states that theres a "Use of uninitialized value in split at line 269. below is the code:
      # Grabs each district from all_store array foreach my $dist_only (@all_store_info) { my @array = split(/ / , $dist_only); #line 269 my $test = @array; next if $test < 2; $distlist = "$array[1] $array[2] $array[3]"; push(@dist_list, $distlist); #print "$distlist\n"; }
        You didn't address the issues I listed in my response. Please re-read that node, and this one:
        How (Not) To Ask A Question - Only Post Relevant Code.

        I want to help you, but you aren't providing the information that is neccesary to do it effectively. Help us help you.

        All it's saying is that $dist_only is empty. You can correct it with.
        foreach my $dist_only (@all_store_info) { next if (!$dist_only); my @array = split(/ / , $dist_only);
        But that is FAR from worst problem with that code. Re-read these posts and try to fix all your code before posting again.


        grep
        Mynd you, mønk bites Kan be pretti nasti...
Re: read-only error
by grep (Monsignor) on Aug 24, 2006 at 18:20 UTC
    ok you've got some serious problems - most would be pointed out by use warnings; and use strict;

    It would be also nice to know what line is "line 686"

    # Grabs each district from all_store array foreach $dist_only (@all_store_info) { my @array = split(/ / , $dist_only); my $test = @array; # this returns the number of elements not the last array pos # so a 3 element array will return 3 next if $test < 2; # this will only filter out 1 element lines # because $test is the num of elements $distlist = "$array[1] $array[2] $array[3]"; # first off you are pulling the 2nd 3rd and 4th elements # not 1st thru 3rd ($array[0] $array[1] $array[2]) # this is also string data (contains spaces) not numeric push(@dist_list, $distlist); #print "$distlist\n"; } @dist_list = sort { $a <=> $b } @dist_list; #you are sorting string data with the numeric op. #( "<=>" is numeric - "cmp" is string ) my %uniq; undef @uniq{@dist_list}; @dist_list = keys %uniq;
    Clean this up and make it do what you want - add use warnings and use strict and then repost this (pointing out the line number in question. Then we can help.


    grep
    Mynd you, mønk bites Kan be pretti nasti...
Re: read-only error
by shmem (Chancellor) on Aug 24, 2006 at 17:58 UTC
    That means the open filehandle LIST, 22 lines read so far.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: read-only error
by Anonymous Monk on Aug 24, 2006 at 18:20 UTC
    The Read only error accurred on line 868 which is :
    my %uniq;
    could someone explain to me what the last 3 line is doing line by line?

    Thanks,
    Paul

      The Read only error accurred on line 868 which is : my %uniq; could someone explain to me what the last 3 line is doing line by line?

      Yes but you have more problems as I stated above;

      my %uniq; # create a hash called %uniq undef @uniq{@dist_list}; # takes the array @dist_list as keys to create in %uniq # each with the value undef. # Since you can only have 1 unique key in a hash this # has the effect of filtering out repeats #ex. # # %uniq = { # '1 2 3' => undef, # '4 5 6' => undef, # '5 6 7' => undef # }; @dist_list = keys %uniq; # this pulls the keys from %uniq and assings them to @dist_list
      So this code is not a problem - you need to fix the other problems first.


      grep
      Mynd you, mønk bites Kan be pretti nasti...

      Sometimes, the line number in error messages are off by a bit. I think that's the case here.

      undef @uniq{@dist_list};
      is equivalent or similar to
      $uniq{$_} = undef for @dist_list;

      Together, the three lines remove duplicate items in @dist_list, assuming @dist_list only contains strings. (Anything in @dist_list which isn't a string is first converted to a string.) The order of the items in @dist_list is not guaranteed to remain unchanged.

      By the way, it's <code>..</code> (or <c>..</c>), not <code>..<code/>.