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
| [reply] [d/l] [select] |
|
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
| [reply] [d/l] |
|
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
| [reply] |
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/;
| [reply] [d/l] |
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. | [reply] [d/l] [select] |
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?
| [reply] |
|
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".
| [reply] [d/l] [select] |
|
| [reply] |
|
another way to put it is that a list is read only, while an array is not.
| [reply] |
|
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
| [reply] [d/l] [select] |