Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
You tried, directly or indirectly, to change the value of a constant. This type of error frequently occurs at a distance and is difficult to trace. The magic of $_ is often involved, but is not responsible.

Common causes:

  1. Treating a loop variable as an lvalue
  2. Modifying $_ inside foreach, map or grep
  3. Modifying elements of @_ directly
  4. Modifying $a or $b inside sort
  5. Autovivifying $a or $b inside sort
  6. Modifying an unlocalized $_

Treating a loop variable as an lvalue

for my $x (1,2) { $x++; }
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.

Modifying $_ inside foreach, map or grep

for (1,2) { chomp; } for ("foo", @list) { s/foo/bar/; } @array = map { $_++ } (1,2); @array = grep { $_++ } (1,2);
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.

Modifying elements of @_ directly

sub incr { $_[0]++; } my $n = 1; incr($n); # good incr(1); # bad
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.

Modifying $a or $b inside sort

@array = sort { $a++ } (1,2);
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.

Autovivifying $a or $b inside sort

my @bad; $bad[0] = [1]; $bad[2] = [2]; @bad = sort {$a->[0] <=> $b->[0]} @bad;
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.

Modifying an unlocalized $_

for (1,2) { my $data = prompt_user(); } sub prompt_user { print "Enter a number\n"; while (<STDIN>) { # Do stuff } }
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'.

The error will also occur in this simplified scenario:

for (1,2) { while (<STDIN>) { } }

Guidelines to avoid read-only errors:

  1. Don't treat loop variables as a lvalue if there is any chance a constant value will be included
  2. Don't modify an unlocalized $_
  3. Don't modify $_ inside map or grep
  4. Don't modify $a or $b inside sort
  5. Don't dereference $a or $b inside sort without checking that they exist and are references
  6. Don't use $_ for the loop variable unless it is a very trivial loop
  7. Don't modify elements of @_ directly

Notes

Lists With Constant Values

Within the context of this document the important thing to understand is what expressions result in modifiable objects. The following expressions have constants in them:
$_++ for (1,2); $_++ for (1,@array); @array = map {$_++} (1,@array);
And the following are safe:
my @array = (1,2); for (@array) { $_++; }
my ($x,$y) = (1,2); for ($x,$y) { $_++; }
For an explanation of lists versus arrays I recommend the following:

In reply to Common Causes for "Modification of a read-only value attempted" by imp

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others pondering the Monastery: (8)
    As of 2014-12-21 10:52 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      Is guessing a good strategy for surviving in the IT business?





      Results (104 votes), past polls