Welcome to the Monastery | |
PerlMonks |
Common causes:
Treating a loop variable as an lvalue
In this example $x is aliased to the constant '1', so when the loop body attempts to increment $x an error is triggered. See Lists With Constant Values for more details.for my $x (1,2) { $x++; }
In all of these examples $_ is aliased to a constant, and when the loop body attempts to modify $_ an error is triggered. See Lists With Constant Values for more details.for (1,2) { chomp; } for ("foo", @list) { s/foo/bar/; } @array = map { $_++ } (1,2); @array = grep { $_++ } (1,2);
Modifying elements of @_ directly allows you to modify the variable that was passed to the function. For example, in the above example $n is now 2. But an error will occur when a constant is passed, as in the second call.sub incr { $_[0]++; } my $n = 1; incr($n); # good incr(1); # bad
It is permissible (but ill-advised) to modify $a and $b within sort. However, modifying a constant that is aliased to $a or $b is still an error.@array = sort { $a++ } (1,2);
The variables $a and $b are aliased to each item in the list being sorted, and as such modifying them is possible - but will cause an error if the current element is unmodifiable. A common cause of this is sorting an array of references when where the list has a gap. In this situation $a will be undef, and autovivification by dereferencing will trigger an error.my @bad; $bad[0] = [1]; $bad[2] = [2]; @bad = sort {$a->[0] <=> $b->[0]} @bad;
This example will cause an error because the for loop aliases $_ to the literal '1', and then calls prompt_user which attempts to read a line from STDIN and store it in $_ - which is still aliased to '1'.for (1,2) { my $data = prompt_user(); } sub prompt_user { print "Enter a number\n"; while (<STDIN>) { # Do stuff } }
The error will also occur in this simplified scenario:
for (1,2) { while (<STDIN>) { } }
And the following are safe:$_++ for (1,2); $_++ for (1,@array); @array = map {$_++} (1,@array);
my @array = (1,2); for (@array) { $_++; }
For an explanation of lists versus arrays I recommend the following:my ($x,$y) = (1,2); for ($x,$y) { $_++; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Common Causes for "Modification of a read-only value attempted"
by techcode (Hermit) on Jul 15, 2009 at 10:59 UTC | |
Re: Common Causes for "Modification of a read-only value attempted"
by maxx27 (Novice) on Jul 10, 2016 at 15:12 UTC |