Is this a perl bug?

0 views
Skip to first unread message

Ted Hopp

unread,
Sep 13, 2003, 10:02:22 PM9/13/03
to
Why does the following program print "Undefined!"? Shouldn't the subroutine
leave the value of $x alone? (I can understand it clobbering $_, but $x?)

#!/usr/bin/perl -w
use strict;
sub readZip() {
open FH, '/dev/null';
while (<FH>) { print "Got something!\n"; }
}

my $x = 'hi';
for ($x) { readZip(); }
print "Undefined!\n" unless defined $x;

(I'm using perl 5.6.1)

Thanks,

Ted Hopp
t...@newslate.com


dw

unread,
Sep 15, 2003, 5:09:28 PM9/15/03
to

"Ted Hopp" <t...@newslate.com> wrote in message
news:bk0i3i$ekv$1...@bob.news.rcn.net...

> Why does the following program print "Undefined!"? Shouldn't the
subroutine
> leave the value of $x alone? (I can understand it clobbering $_, but $x?)
>
> #!/usr/bin/perl -w
> use strict;
> sub readZip() {
> open FH, '/dev/null';
> while (<FH>) { print "Got something!\n"; }
> }
>
> my $x = 'hi';
> for ($x) { readZip(); }
> print "Undefined!\n" unless defined $x;
>

for ($x) { .... } makes $_ an alias for $x
inside readZip(), while (<FH>) modifies $_ (which is still an alias for $x)

maybe adding
local $_;
or
my $_;
inside readZip will produce the results you want

slimzhao

unread,
Sep 15, 2003, 8:10:35 PM9/15/03
to
"Ted Hopp" <t...@newslate.com> wrote in message news:<bk0i3i$ekv$1...@bob.news.rcn.net>...

It's not a perl's bug.
for ($x) { readZip(); }
This loop run once, $_ is set to $x, in actually, $_ is an alias of
$x, so if something in the for BLOCK changes $_, $x also changed,
while, now look at your readZip.
while(<FH>) { print "Got something!\n"; }
The loop's BLOCK doesn't run, but <FH> is evaluted once. while(<FH>)
is same as
while($_=<FH>), so, $_ is set to undef, and, the outer $x is set to
undef. That's it.

If you change your while statement to something like:
while(my $line = <FH> ) { .. }
everything is OK.

slimzhao

unread,
Sep 15, 2003, 8:26:01 PM9/15/03
to
"Ted Hopp" <t...@newslate.com> wrote in message news:<bk0i3i$ekv$1...@bob.news.rcn.net>...

the $_ is local in the for BLOCK, so it's visible for all the chained
subroutine in runtime, redeclare $_ as local will break the rules.
sub readZip()
{
local $_; #This will protect the outer $_ well.
...
}

I heard that "There's more than one way to do it", ok, here's the No 2

No.3
change your for statement to:
for $y($x) { ... }

Ted Hopp

unread,
Sep 16, 2003, 7:40:39 PM9/16/03
to
Thanks, everyone.

Ted Hopp
t...@newslate.com


Reply all
Reply to author
Forward
0 new messages