Re: a question about for and foreach



rainman wrote:
Hi,

Hello,

I got a very strange problem about for and foreach. I don't
understand why.

The following is my program:

===
#!/usr/bin/perl

use strict;

my @array = (1, 2, 3);
print @array;

foreach (@array) {
print $array[0];
print $array[1];
print $array[2];
open FILE, "<bbb";
while (<FILE>) {
print "hello\n";
}
close FILE;
}

print @array;
print $array[1];
===

"bbb" just a file contains only one line like "kdfjkdfjlsjfslkf".

My question is, why @array are changed after this foreach loop!!!

The documentation from perlsyn.pod:

perldoc perlsyn
[ SNIP ]
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.

The "foreach" keyword is actually a synonym for the "for" keyword,
so you can use "foreach" for readability or "for" for brevity. (Or
because the Bourne shell is more familiar to you than csh, so
writing "for" comes more naturally.) If VAR is omitted, $_ is set
to each value.

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.

What your program does:

foreach $_ (@array) {
open FILE, "<bbb";
while ($_ = <FILE>) {
print "hello\n";
}
close FILE;
}

So $_ is an alias to the current element of @array and the while loop assigns to $_ which changes the current value of that element.

What you should do:

foreach my $item ( @array ) {
open FILE, '<', 'bbb' or die "Cannot open 'bbb' $!";
while ( my $line = <FILE> ) {
print "hello\n";
}
close FILE;
}



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

.



Relevant Pages

  • Re: foreach statement output
    ... by using a 'for' statement instead of the foreach loop: ... and I will use the array to generate a string. ... know about foreach loop workings. ...
    (comp.infosystems.www.authoring.cgi)
  • Re: foreach statement output
    ... know about foreach loop workings. ... I've got an incoming array of unknown ... The Perl Cookbook ... My big confusion over this foreach issue is I failed to realize that the ...
    (comp.infosystems.www.authoring.cgi)
  • Re: Strange behaviour
    ... Personally, I would use the foreach version, as it is easier to read. ... bool AllNegative{ ... besides the difference between for and foreach the first example will always test each element of the array while the second example only tests until it finds the first non-negative. ... This is independant of for/foreach since also a for loop can be exited with return ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: safe to delete elements of array in foreach
    ... (normally this is not the case but not sure in php) ... I make it a habit not to delete entries in a foreach() loop. ... build an array of keys I want to delete, and after the loop ends, ...
    (comp.lang.php)
  • Re: tr operator weirdness
    ... You need to read about foreach loops. ... If any element of LIST is an lvalue, you can modify it by ... modifying VAR inside the loop. ...
    (comp.lang.perl.misc)