Re: a question about for and foreach

[email protected] ("John W. Krahn")
Newsgroups perl.beginners
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.