Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Still don't undersand "Modification of a read-only value attempted" error

by Anonymous Monk
on Jun 20, 2012 at 21:49 UTC ( [id://977481]=perlquestion: print w/replies, xml ) Need Help??

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

I guess I am stuborn. I have read several of the posts which explain this error. I guess I am missing a key point somewhere. What is different about "$item" when used in the example below. It seems to me that it is always a constant.

test5:{ @list = ("abcdef", "ghijkl", "Dumbo"); foreach $item ("abcdef", "ghijkl", "Dumbo" ){ #This fails "modify +ing a Read only Constant" # foreach $item (@list ){ # this works $item =~ s/abc/zzzzzz/ ; print (" $item \n"); } }
  • Comment on Still don't undersand "Modification of a read-only value attempted" error
  • Download Code

Replies are listed 'Best First'.
Re: Still don't undersand "Modification of a read-only value attempted" error
by moritz (Cardinal) on Jun 20, 2012 at 21:56 UTC

    The for-loop aliases the variable (here $item) to the list elements. If the list element is a literal, s/// cannot modify it.

    On the other hand @list = ("abcdef", "ghijkl", "Dumbo"); puts the elements into an array, and you can always change array elements.

    Or phrased differently, it's the same as

    "abcdef" = 3; # doesn't work $list[0] = 3; # works
      Also note that range operator behaves differently than a hardcoded list:
      s/[u3]/X/, print for 1 .. 10, "a" .. "z"; # ok s/[u3]/X/, print for 1, 2, 3, 4, "a", "b", "u", "z"; # error again

        I find this interesting — and surprising! Range Operators in perlop has:

        Binary ".." is the range operator.... In list context, it returns a list of values .... If the left value is greater than the right value then it returns the empty list. ... In the current implementation, no temporary array is created when the range operator is used as the expression in foreach loops...

        This certainly makes it seem as though the range operator (in list context) returns an ordinary list, so why the difference in behaviour?

        Is this documented anywhere? Or is it an undocumented feature?

        Athanasius <°(((><contra mundum

Re: Still don't undersand "Modification of a read-only value attempted" error
by derby (Abbot) on Jun 20, 2012 at 22:02 UTC

    $item is always an alias. In the 'failing' foreach, it's an alias to a constant in a list and hence not modifiable (where would perl save the modification?) For the 'working' foreach, $item is an alias to an array element which is modifiable (since we have some place to save the modification). So either use your array or make a copy of the aliased item:

    (my $val = $item) =~ s/abc/zzzzzz/;

    -derby
Re: Still don't undersand "Modification of a read-only value attempted" error
by frozenwithjoy (Priest) on Jun 20, 2012 at 22:21 UTC
    Another way to think of it is that the constants (e.g., "abcdef") are immutable, whereas variables (e.g., @list[0]) holding them are mutable. Another thing... you name your array "@list", but there is a difference between arrays and lists. Understanding this may help to clear up some of the confusion.
Re: Still don't undersand "Modification of a read-only value attempted" error
by Dan.Pinvidic (Initiate) on Jun 20, 2012 at 22:24 UTC

    OK, I understand the difference between a variable and a constant. But my problem is that I can't grasp exactly when Perl decides which one it is. My thoughts are..."abcdef" is a constant of type string. It looks like in both cases, it is eventually assigned to $item. If it is assigned to a element of @list first, then assigned to $item in the foreach statement, it still seems that $item contains a string. It seems like in the end, $item contains the same thing. Now does this have somehting to do with $_ and is the error msg really refering to $_ as the Read Only constant?

      in both cases, it is eventually assigned to $item.

      No, nothing is being assigned to $item. Rather, in the error case, $item becomes an alias, i.e. an alternate way to access the same instance of the constant string "abcdef".

        BING.....Light bulb just came on....Thank you so much. I was pulling my hair out...and I don't have any to spare....Thanks again

      another way to put it is that a list is read only, while an array is not.
      The error is telling you that you are trying to modify one of the constants in your list:
      ("readonlyval1","readonlyval2","readonlyval3")
      You are allowed to modify values in an array, which are not readonly, like:
      $item[0]=~s/foo/bar; $item[1]="something_else"; #no can do: something=something_else

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://977481]
Approved by moritz
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-25 09:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found