Discussion:
Modification of a read-only value attempted - why?
(too old to reply)
Tony Lawrence
2006-09-15 16:37:09 UTC
Permalink
Can someone explain this to me?

(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)

Test code:

#!/usr/bin/perl -w
# no problem here
caroomba("first");


@dayval=qw(foo ba);
foreach $dayval (@dayval) {
# no problem here
caroomba($dayval);
}


foreach $dayval ("foo2","ba2") {
# no problem here either
caroomba($dayval);
}


foreach ("foo3","ba3") {
# doesn't like this
$dayval=$_;
caroomba($dayval);
}



sub caroomba {
my $p=shift;
print "Caroomba called $p\n";
open(I,"./t");
while (<I>) {
# stuff..
}
close I;
}


When run, that produces:


Caroomba called first
Caroomba called foo
Caroomba called ba
Caroomba called foo2
Caroomba called ba2
Caroomba called foo3 Modification of a read-only value attempted at
./t.pl line 23, <I> line 23.

Why?

Something to do with anonymous arrays, but I don't grok it.
Brian McCauley
2006-09-15 17:08:31 UTC
Permalink
Post by Tony Lawrence
Can someone explain this to me?
(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)
[still rather long ]

I've abberviated your example to:

for ("foo3") {
while (<DATA>) {
}
}
__END__

The <> construct in a while() performs an implicit assignment to the
global variable $_ but does _not_ perform an implicit local($_) in the
way for() does.

The for() makes the global variable $_ an alias for the readonly value
"foo3".
Post by Tony Lawrence
Something to do with anonymous arrays, but I don't grok it.
No, nothing to do with arrays.

The obvious, but _wrong_ solution is to insert local($_) before the
while(<...>). This will work 99.99% of the time but that last time in
10000 $_ will be aliased to an element of a tied agregate (HASH or
ARRAY) and then local($_) will do evil things.

The correct fix is either to local(*_) or to avoid the implicit
assignment feature completely.

Note that an unfortunate side effect of local(*_) is that is localizes
@_ etc too. You can get arround this with the rather peverse looking
code...

local(*_) = do{ \my $underscore };
a***@radom.zrz.tu-berlin.de
2006-09-15 17:13:55 UTC
Permalink
Post by Tony Lawrence
Can someone explain this to me?
(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)
[snip code that doesn't show the problem]
Post by Tony Lawrence
foreach ("foo3","ba3") {
# doesn't like this
$dayval=$_;
caroomba($dayval);
}
sub caroomba {
my $p=shift;
print "Caroomba called $p\n";
open(I,"./t");
while (<I>) {
# stuff..
}
close I;
}
Caroomba called foo3 Modification of a read-only value attempted at
./t.pl line 23, <I> line 23.
Why?
Something to do with anonymous arrays, but I don't grok it.
Which anonymous array? I don't see any.

The problem is the nesting (through a sub call) of the outer
for-loop and the inner while-loop. The outer "for" aliases $_
to the read-only literal "foo3". This alias is still in effect
inside the sub. The while-loop now tries to use the variable
$_ as its implicit variable. Since $_ is aliased to a read-only
value, that fails with the error you see.

Anno
Tony Lawrence
2006-09-16 09:57:03 UTC
Permalink
Post by a***@radom.zrz.tu-berlin.de
Post by Tony Lawrence
Can someone explain this to me?
(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)
[snip code that doesn't show the problem]
Post by Tony Lawrence
foreach ("foo3","ba3") {
# doesn't like this
$dayval=$_;
caroomba($dayval);
}
sub caroomba {
my $p=shift;
print "Caroomba called $p\n";
open(I,"./t");
while (<I>) {
# stuff..
}
close I;
}
Caroomba called foo3 Modification of a read-only value attempted at
./t.pl line 23, <I> line 23.
Why?
Something to do with anonymous arrays, but I don't grok it.
Which anonymous array? I don't see any.
The problem is the nesting (through a sub call) of the outer
for-loop and the inner while-loop. The outer "for" aliases $_
to the read-only literal "foo3". This alias is still in effect
inside the sub. The while-loop now tries to use the variable
$_ as its implicit variable. Since $_ is aliased to a read-only
value, that fails with the error you see.
Anno
OK, I see it now. If the subroutine is modified to add

print "\$_ is $_\n";

it shows up quickly:

..
Use of uninitialized value in concatenation (.) or string at ./t.pl
line 21.
$_ is
Caroomba called ba2
$_ is foo3
Caroomba called foo3
Modification of a read-only value attempted at ./t.pl line 24.

I never realized that $_ would be passed down to a subroutine.. I
thought the sub would have its own $_.. but there it is.

So.. this isn't considered a bug or flaw in Perl? This is intended
behavior?
a***@radom.zrz.tu-berlin.de
2006-09-16 10:26:32 UTC
Permalink
Post by Tony Lawrence
Post by a***@radom.zrz.tu-berlin.de
Post by Tony Lawrence
Can someone explain this to me?
(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)
[snip code that doesn't show the problem]
Post by Tony Lawrence
foreach ("foo3","ba3") {
# doesn't like this
$dayval=$_;
caroomba($dayval);
}
sub caroomba {
my $p=shift;
print "Caroomba called $p\n";
open(I,"./t");
while (<I>) {
# stuff..
}
close I;
}
Caroomba called foo3 Modification of a read-only value attempted at
./t.pl line 23, <I> line 23.
Why?
Something to do with anonymous arrays, but I don't grok it.
Which anonymous array? I don't see any.
The problem is the nesting (through a sub call) of the outer
for-loop and the inner while-loop. The outer "for" aliases $_
to the read-only literal "foo3". This alias is still in effect
inside the sub. The while-loop now tries to use the variable
$_ as its implicit variable. Since $_ is aliased to a read-only
value, that fails with the error you see.
Anno
OK, I see it now. If the subroutine is modified to add
print "\$_ is $_\n";
..
Use of uninitialized value in concatenation (.) or string at ./t.pl
line 21.
$_ is
Caroomba called ba2
$_ is foo3
Caroomba called foo3
Modification of a read-only value attempted at ./t.pl line 24.
I never realized that $_ would be passed down to a subroutine.. I
thought the sub would have its own $_.. but there it is.
$_ is a package variable. It is the same whenever you access it.
Post by Tony Lawrence
So.. this isn't considered a bug or flaw in Perl? This is intended
behavior?
It's expected behavior.

Anno
Tony Lawrence
2006-09-16 16:19:36 UTC
Permalink
Post by a***@radom.zrz.tu-berlin.de
Post by Tony Lawrence
Post by a***@radom.zrz.tu-berlin.de
Post by Tony Lawrence
Can someone explain this to me?
(full text at http://aplawrence.com/Unix/perl_readonly.html ,
abbreviated version here)
[snip code that doesn't show the problem]
Post by Tony Lawrence
foreach ("foo3","ba3") {
# doesn't like this
$dayval=$_;
caroomba($dayval);
}
sub caroomba {
my $p=shift;
print "Caroomba called $p\n";
open(I,"./t");
while (<I>) {
# stuff..
}
close I;
}
Caroomba called foo3 Modification of a read-only value attempted at
./t.pl line 23, <I> line 23.
Why?
Something to do with anonymous arrays, but I don't grok it.
Which anonymous array? I don't see any.
The problem is the nesting (through a sub call) of the outer
for-loop and the inner while-loop. The outer "for" aliases $_
to the read-only literal "foo3". This alias is still in effect
inside the sub. The while-loop now tries to use the variable
$_ as its implicit variable. Since $_ is aliased to a read-only
value, that fails with the error you see.
Anno
OK, I see it now. If the subroutine is modified to add
print "\$_ is $_\n";
..
Use of uninitialized value in concatenation (.) or string at ./t.pl
line 21.
$_ is
Caroomba called ba2
$_ is foo3
Caroomba called foo3
Modification of a read-only value attempted at ./t.pl line 24.
I never realized that $_ would be passed down to a subroutine.. I
thought the sub would have its own $_.. but there it is.
$_ is a package variable. It is the same whenever you access it.
Post by Tony Lawrence
So.. this isn't considered a bug or flaw in Perl? This is intended
behavior?
It's expected behavior.
Anno
Ayup. I see it now, thanks. The Camel book actually tells you that
the default variable for angle bracket input is the global $_ and not
the local $_ (p.81 of the 3rd edition, otherwise look for the section
on Line Input (Angle) Operator).

I'm sure I read that at least once, but the significance escaped me -
thanks again.
Michele Dondi
2006-09-19 14:45:59 UTC
Permalink
Post by a***@radom.zrz.tu-berlin.de
$_ is a package variable. It is the same whenever you access it.
Post by Tony Lawrence
So.. this isn't considered a bug or flaw in Perl? This is intended
behavior?
It's expected behavior.
It may be interesting to mention that bleadperl provides both a
lexical $_ and means to use it in constructs that resort on $_. I only
gave a quick peek into those features quite a lot of time ago and I
can't remember the details offhand, though...


Michele
--
{$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
(($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
.'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
Loading...