in reply to How to fix error: Modification of a read-only value

Dear Monks--
Sorry if I haven't provided enough information

O.K. Here is all the code I can think is relevant. You wanted to know what line was generating the error ("Modification of a read-only value attempted"). It was the last line I'm giving here; i.e. the sort line. Is it worth noting that elsewhere in the program I am able to access any element of the @courselist array without problem?
foreach $try (@text){ $try =~/^(.*?)\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|(.*?) +\|(.*?)\|(.*?)$/gs or die "<br />problem with $try<br />"; my $Institution = $1; my $CourseNumber = $2; my $Professor = $3; my $Enrollment = $4; ........ if (!$CourseNumber && !$Institution){last;}; if ($CourseNumber ne $LastCourseNumber){ $courseindex = $courseindex + 1; $courselist[$courseindex] = [$Institution, $CourseNumber, $Professor, +$CourseTitle, $Enrollment]; }; $LastCourseNumber = $CourseNumber; }; @courselist = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @co +urselist;
To reiterate, what I'd like to do is to sort @courselist by $courselist[n][0] (i.e. $Institution, and within that sort, by $courselist[n][1], i.e. $CourseNumber.

This is an example of what I have in @courselist:
$courselist[0] = ["UM", "CS 34", "Smith", "34"] $courselist[1] = ["AC", "PHIL 13", "Barry", "45"] $courselist[2] = ["UM", "BIO 567", "Houlihan", "12"]
and I want it to end looking like this:
$courselist[0] = ["AC", "PHIL 13", "Barry", "45"] $courselist[1] = ["UM", "BIO 567", "Houlihan", "12"] $courselist[2] = ["UM", "CS 34", "Smith", "34"]

I don't understand why I'm getting the error message, and I'm still not sure about the sort...

Thanks for your continuing efforts!

Replies are listed 'Best First'.
Re^2: How to fix error: Modification of a read-only value
by GrandFather (Saint) on Aug 13, 2006 at 22:12 UTC

    This is still not a piece of code that I can run on my machine and see your problem. Distil your code down to a stand alone sample that exhibits the problem. There are too many unknowns in the code you have provided. I say again, read I know what I mean. Why don't you?.

    Note that your regex is probably much better done as a split:

    my ($Institution, $CourseNumber, $Professor, $Enrollment) = split '|', + $try;

    Oh, hold on a moment, my esp cells are kicking in. Here is the sample you should have posted:

    use warnings; use strict; my @courselist; my @text = 'UM|CS 34|Smith|34'; my $courseindex = 0; foreach my $try (@text){ my ($Institution, $CourseNumber, $Professor, $Enrollment) = split +'|', $try; $courseindex = $courseindex + 1; $courselist[$courseindex] = [$Institution, $CourseNumber, $Professor, $Enrollment]; }; @courselist = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1]} @cou +rselist;

    And the answer is that you preincrement $courseindex so the first element is placed at index 1, but Perl generally starts arrays at 0 and trying to dereference aan undefined value in the sort (element 0) is generating your error.

    Your code would be better written as:

    use warnings; use strict; my @courselist; my @text = 'UM|CS 34|Smith|34'; foreach my $try (@text){ my ($Institution, $CourseNumber, $Professor, $Enrollment) = split +'|', $try; push @courselist, [$Institution, $CourseNumber, $Professor, $Enrol +lment]; }; @courselist = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1]} @cou +rselist;

    DWIM is Perl's answer to Gödel
Re^2: How to fix error: Modification of a read-only value
by graff (Chancellor) on Aug 13, 2006 at 23:29 UTC
    Here is all the code I can think is relevant.

    Well, you might need to think a little harder -- or read our replies more carefully... But, okay, here is a working script based on what you've posted, putting together some sample data from your earlier post, and adding some other things that you haven't included yet, like assigning data to @text. (I removed "$CourseTitle", but if you really need it, I hope you can figure out how to fit it in with this approach.) Essentially, I'm providing the thing that GrandFather asked for (except that this version does not get the run-time error that you get, so it doesn't "demonstrate the problem"):

    use strict; use Data::Dumper; my @text = <DATA>; my @courselist; my $LastCourseNumber; for (@text) { my ( $Institution, $CourseNumber, $Professor, $Enrollment ) = spli +t /\|/; last unless ( $CourseNumber && $Institution); if ($CourseNumber ne $LastCourseNumber) { push @courselist, [ $Institution, $CourseNumber, $Professor, $Enrollment]; $LastCourseNumber = $CourseNumber; } } print Dumper( \@courselist ); @courselist = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @co +urselist; print Dumper( \@courselist ); __DATA__ UM|CS 34|Somebody|3 AC|PHIL 13|Another Person|8 UM|BIO 567|Someone Else|20
    (update: the "last" condition in loop had been like the OP code ("if..."), but I think using "unless" makes more sense here -- this way, either variable being empty will exit the loop.)

    This does what you want to do (sort the array). I expect there's still more stuff in your own script that you need to fold in, and maybe when that other stuff is included, you'll still get an error. If so, that means the problem is still somewhere in the code that you have not shown us.

Re^2: How to fix error: Modification of a read-only value
by shmem (Chancellor) on Aug 21, 2006 at 06:14 UTC
    Don't say
    $courseindex = $courseindex + 1;

    say rather

    $courseindex++;
    if you need $courseindex for anything other than storing the array references in the right slot of @courselist.

    You should then set $courseindex initially to 0 and increment it at the proper place, i.e. after having filled an array slot.

    If you don't need to keep track of the index and just want to push a value (anonymous array) onto @courselist, do so:

    push @courselist, [$Institution, $CourseNumber, $Professor, $CourseTit +le, $Enrollment];

    --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}