in reply to Modification of a read-only value attempted?!?

In the case of for my $x (1) { }, the variable $x is a reference to the value in brackets which is constant.

Consider this: perl -le "my $y = 2; for my $x ($y) { $x = 1; print $y }" When we change $x, we change the underlying $y. So the output is 1

Replies are listed 'Best First'.
Re^2: Modification of a read-only value attempted?!?
by kikuchiyo (Hermit) on Jan 07, 2024 at 21:07 UTC

    Yes, yes, the loop variable in for(each) aliases elements of the list.

    But why is the loop variable read-only if there is only a single numeric (or string) literal in the list?

    AFAICT the program works as expected in all other cases.
    perl -MDevel::Peek -le 'for my $x ([1]->[0]) {Dump $x; $x = pack "I", +$x; Dump $x}' # OK perl -MDevel::Peek -le 'my $y=1; for my $x ($y) {Dump $x; $x = pack "I +", $x; Dump $x}' # OK perl -MDevel::Peek -le 'sub one(){1} for my $x (one) {Dump $x; $x = pa +ck "I", $x; Dump $x}' # OK perl -MDevel::Peek -le 'for my $x (0+1) {Dump $x; $x = pack "I", $x; D +ump $x}' # OK!!! perl -MDevel::Peek -le 'for my $x ("1"."1") {Dump $x; $x = pack "I", $ +x; Dump $x}' # OK perl -MDevel::Peek -le 'for my $x ("1") {Dump $x; $x = pack "I", $x; D +ump $x}' # Error, read-only perl -MDevel::Peek -le 'for my $x (1) {Dump $x; $x = pack "I", $x; Dum +p $x}' # Error, read-only

    Experimenting on perlbanjo.com, it seems that this behavior goes back to at least Perl 5.8.

      The difference is that in for my $x (1) {...} the 1 is a literal constant. (0..1) on the other hand is an expression evaluating to the list (0,1). The loop is aliasing to the anonymous elements of the list, not to the literal boundaries in (0..1).

      Perhaps it is helpful to consider that for my $x (0,1) {...} also dies with Modification of a read-only value attempted at -e line 1.

      • 0+1 is an expression: ok!
      • "1" is a literal constant: not ok!
      • (0..1) is an expression: ok!
      • (0,1) is a literal list: not ok!
        *x = \1 also used to be a common way to define "constants".

        In the OP's case the aliased $x and 1 should have the same reference.

        But there is no point in making temporarily generated values read only, almost all code would break then.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

Re^2: Modification of a read-only value attempted?!?
by jo37 (Curate) on Jan 07, 2024 at 20:57 UTC

      While 0 and 1 evaluate to a constant, 0..1 evaluates to two scalars which aren't constants.

      That said, for (0..1) doesn't actually use the range operator as an optimization. But the result is the same.