Perl Bug???

M

Mike Thorland

This was tested with Perl 5.8.5 and 5.6.1

Test Program:

sub Foo() {
print "array_test: @array_test\n";

$shellcmd = "/bin/echo hi'";
open SHELLCMD, "$shellcmd |" or
die "Could not open shellcmd $!\n";
while (<SHELLCMD>) { } # do nothing - works with backticks not with shell
loop
close SHELLCMD;

print "array_test: @array_test\n";
}

@array_test = ("one");
for (@array_test) {
Foo();
}

Output:

array_test: one
array_test:

Why does array_test become unitialized? Yet if I add a loop variable for
@array_test ...

for $bar (@array_test) {
Foo();
}

It works:

Output:

array_test: one
array_test: one
 
P

Paul Lalli

Subject: Perl Bug???

Whenever you find yourself wanting to type something like that, you
should really count to 10 and ask yourself what's more likely - that
there's a new and undiscovered bug in the language that's been used
worldwide for 20 years that you just happened to find, or that you
either did something wrong or don't understand the results you're
seeing.
This was tested with Perl 5.8.5 and 5.6.1

Test Program:

sub Foo() {
print "array_test: @array_test\n";

$shellcmd = "/bin/echo hi'";
open SHELLCMD, "$shellcmd |" or
die "Could not open shellcmd $!\n";
while (<SHELLCMD>) { } # do nothing - works with backticks not with shell
loop
close SHELLCMD;

print "array_test: @array_test\n";

}

@array_test = ("one");
for (@array_test) {
Foo();

}

Output:

array_test: one
array_test:

Why does array_test become unitialized?

It doesn't. The only element of @array_test, however does. If you'd
enabled warnings, you would see Perl tell you that you're printing an
undefined value, rather than printing no values. You could also
examine the contents of @array_test more precisely with the
Data::Dumper module.

perldoc perlsyn
describes how for each loop works. When you don't give a loop
iterator variable, Perl localizes $_ and uses that. In your foreach
loop, $_ is an ALIAS to the element of the list you're iterating over,
meaning that changes to $_ will change the list itself.

In your subroutine, you are using $_ implicitly once more, this time
to iterate over the "/bin/echo hi |" shell command's output. In each
iteration of your while loop, $_ gets assigned to the current line of
output. When the output is exhausted, the readline operator (ie,
<SHELLCMD>) returns undef, and so $_ gets the value undef. But
remember that you've already aliased $_ to be the current element of
@array_test. So since you just changed $_, you've also changed the
current element of @array_test.
Yet if I add a loop variable for
@array_test ...

for $bar (@array_test) {
Foo();

}

It works:

Output:

array_test: one
array_test: one

Right, because this example doesn't use the localized $_, so the
function call doesn't get a chance to change your array elements.

Best practice - don't rely on the implicit nature of $_ for either for
loops nor while loops. If you must use $_, then localize it
beforehand. If you'd put the statement "local $_;" before you began
your while loop, you'd be working with a temporary value of $_ that
was not aliased to the foreach's list, and this "bug" would not have
appeared.

Paul Lalli

P.S. To help you see what's happening, please take a look at this
modified program, based off your example:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my @array_test;
sub Foo() {
print "array_test: ", Dumper(\@array_test);

my $shellcmd = "/bin/echo hi'";
open SHELLCMD, "$shellcmd |" or
die "Could not open shellcmd $!\n";
while (<SHELLCMD>) {
print "$. - ", Dumper(\@array_test);
}
close SHELLCMD;

print "array_test: ", Dumper(\@array_test);

}

@array_test = ("one");
for (@array_test) {
Foo();
}
 
B

Bart Lateur

Paul said:
Whenever you find yourself wanting to type something like that, you
should really count to 10 and ask yourself what's more likely - that
there's a new and undiscovered bug in the language that's been used
worldwide for 20 years that you just happened to find, or that you
either did something wrong or don't understand the results you're
seeing.

Pooh. I'm sure then are dozens of bugs in perl. Perl evolves. New bugs
get added every year.
 
U

usenet

Pooh. I'm sure then are dozens of bugs in perl. Perl evolves. New bugs
get added every year.

I don't think Paul was claiming that Perl has no bugs. I think he was
pointing out that it is unlikely that a noob would actually uncover a
genuine bug with nothing more than a small, simple test program (and
that immediately suspecting a language fault instead of user-error is
implausible).
 
M

Mike Thorland

I never realized that in Perl loop variables allow you to directly change
the contents of an array. I always thought they were merely a copy.

Test Program:
@array_test = ("original value");
for $bar (@array_test) {
$bar = "new value";
}
print "array_test: @array_test\n";

Output:
array_test: new value

Thanks!
 
P

Paul Lalli

I never realized that in Perl loop variables allow you to directly
change the contents of an array. I always thought they were merely
a copy.

Like I said, `perldoc persyn`:
LABEL foreach VAR (LIST) BLOCK
. . .
If any element of LIST is an lvalue, you can modify it by
modifying VAR inside the loop. Conversely, if any element
of LIST is NOT an lvalue, any attempt to modify that element
will fail. In other words, the "foreach" loop index
variable is an implicit alias for each item in the list that
you're looping over.

You're quite welcome.

Paul Lalli
 
P

Paul Lalli

Pooh. I'm sure then are dozens of bugs in perl. Perl evolves. New bugs
get added every year.

I don't recall saying anything contrary to that.

When you write a program that doesn't work the way you expect,
however, suspecting a bug in the language is the LAST resort.
Suspecting that you made an error or don't understand is the first.

Paul Lalli
 
M

Michele Dondi

I don't think Paul was claiming that Perl has no bugs. I think he was
pointing out that it is unlikely that a noob would actually uncover a
genuine bug with nothing more than a small, simple test program (and
that immediately suspecting a language fault instead of user-error is
implausible).

Suspecting a bug *is* generally plausible: except that it's generally
expected to reside in wetware.


Michele
 
M

Michele Dondi

I never realized that in Perl loop variables allow you to directly change
the contents of an array. I always thought they were merely a copy.

You assumed wrong:

gin:~ [19:24:50]$ perl -le '@a=qw/foo bar/;$_ x= 2,print for @a'
foofoo
barbar
"Paul Lalli" <[email protected]> wrote in message

You also quoted wrong, BTW.


Michele
 
P

Paul Lalli

I never realized that in Perl loop variables allow you to directly change
the contents of an array. I always thought they were merely a copy.

You assumed wrong:

gin:~ [19:24:50]$ perl -le '@a=qw/foo bar/;$_ x= 2,print for @a'
foofoo
barbar

While you're correct that the OP's assumption was wrong, this example
does not demonstrate that. Here, you're only printing $_ within the
loop. If the OP had been correct and $_ was in fact a copy of the
values of @a, the output would be the same. The example you meant to
type was:
perl -le'@a=qw/foo bar/; $_ x= 2 for @a; print for @a;'

Paul Lalli
 
K

krakle

Whenever you find yourself wanting to type something like that, you
should really count to 10 and ask yourself what's more likely - that
there's a new and undiscovered bug in the language that's been used
worldwide for 20 years that you just happened to find, or that you
either did something wrong or don't understand the results you're
seeing.

There's bugs in every Perl release. Your message implies that the
language hasn't changed or evolved since 1987. Which is silly. A
better point is... it's less than likely that someone who isn't Perl
savvy enough to 'use strict' will find a bug with the language.
 
M

Mike Thorland

Another follow up question. Why does manipulation of $_ in "while loops"
contained in routine Foo() affect the localized implicit $_ in the "for
loop" for @array_test , but "for loops" in routine Foo() do not?

For example if you use a for loop the assignment doesn't affect the original
$_ for loop variable:
sub Foo() {
@array2 = ("one");
for (@array2) { $_ = "new value"; }
}

@array_test = ("original value");
for (@array_test) {
Foo();
}
print "array_test: @array_test\n";

Output:
array_test: original value

Yet if you change the for loop to a while loop the assignment does affect $_
sub Foo() {
@array2 = ("one");
while (@array2) { $_ = shift @array2; $_ = "new value"; }

@array_test = ("original value");
for (@array_test) {
Foo();
}
print "array_test: @array_test\n";


Output:
array_test: new value
 
P

Paul Lalli

There's bugs in every Perl release. Your message implies that the
language hasn't changed or evolved since 1987.

I implied nothing of the sort. Read my message again.
A
better point is... it's less than likely that someone who isn't
Perl savvy enough to 'use strict' will find a bug with the
language.

That is exactly what my message said. Read my message again.

Paul Lalli
 
P

Paul Lalli

Another follow up question. Why does manipulation of $_ in
"while loops" contained in routine Foo() affect the localized
implicit $_ in the "for loop" for @array_test , but "for loops"
in routine Foo() do not?

Once again, I refer you to `perldoc perlsyn`:
Foreach Loops

The "foreach" loop iterates over a normal list value and
sets the variable VAR to be each element of the list in
turn. If the variable is preceded with the keyword "my",
then it is lexically scoped, and is therefore visible only
within the loop. Otherwise, the variable is implicitly
local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with
"my", it uses that variable instead of the global one, but
it's still localized to the loop. This implicit
localisation occurs only in a "foreach" loop.

A foreach loop localizes $_. A while loop does not. That is, the for
loop stores off the current value of $_ before the loop begins, and
restores this value once the loop ends.

Paul Lalli
 
M

Mike Thorland

I see so the even though the for loop creates a "localized" $_ variable, it
is still global and can be manipulated. After the for loop exits the
original $_ variable is restored

sub Foo() {
$_ = "new value";
}

@array_test = ("original value");
$_ = "Global value before entering for loop";
print "BEFORE \$_ = $_\n";
for (@array_test) {
Foo();
}
print "AFTER \$_ = $_\n";
print "array_test: @array_test\n";


Output:
BEFORE $_ = Global value before entering for loop
AFTER $_ = Global value before entering for loop
array_test: new value

Thanks again!!
 
K

krakle

I implied nothing of the sort. Read my message again.

Maybe you should.
"that there's a new and undiscovered bug in the language that's been
used worldwide for 20 years that you just happened to find". The same
version hasn't been used worldwide for 20 years. So obviously it's
VERY possible to stumble upon NEW bugs that didn't even exist before
the previous release (with in a year).
That is exactly what my message said. Read my message again.

Paul Lalli

Maybe you should read it. You didn't write that buddy.
 
P

Paul Lalli

Maybe you should.
"that there's a new and undiscovered bug in the language that's
been used worldwide for 20 years that you just happened to
find". The same version hasn't been used worldwide for 20
years. So obviously it's VERY possible to stumble upon NEW bugs
that didn't even exist before the previous release (with in a
year).

POSSIBLE, yes. LIKELY, for a newbie to Perl? No.
Maybe you should read it. You didn't write that buddy.

Are you dense or just a troll? I honestly can't tell. I asked
whether it's more likely that there's a new bug THAT THE OP JUST
HAPPENED TO FIND or that the OP made a mistake. I did not ANYWHERE
say it was unlikely there was a bug in Perl.

Regardless, I'm done with you. You're not worth any further wastes of
my time.

Paul Lalli
 
K

krakle

POSSIBLE, yes. LIKELY, for a newbie to Perl? No.


Are you dense or just a troll? I honestly can't tell.

By your lack of manners I'm just going to assume you have poor social
skills.
I asked
whether it's more likely that there's a new bug THAT THE OP JUST
HAPPENED TO FIND or that the OP made a mistake. I did not ANYWHERE
say it was unlikely there was a bug in Perl.

By your 20 year example you imply (perhaps not intentionally) that
it's unlikely to find a bug in Perl because it's been around for 20
years. I only pointed out there has been several releases with in that
time span all having their own bugs unique to the previous versions...
It's an evolving languaging.. Bugs are expected Paul.
Regardless, I'm done with you. You're not worth any further wastes of
my time.

Perhaps lack of Social Skills AND Manners. I'm just going to HOPE you
are young and in time your moody attitude will improve.
 
B

Bart Lateur

Paul said:
POSSIBLE, yes. LIKELY, for a newbie to Perl? No.

Uh, why not?

Whenever my 2 year old is at the keyboard of my computer, he almost
immediately succeeds in making it do stuff I didn't know it could do
(like putting my computer in standby mode), just by hitting a few
unexpected keys.

Newbies are *very likely* to find bugs old users never stumble upon,
just because they do things old user never would do.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top