|There's more than one way to do things|
Re: What Is Going On Here ?????by autark (Friar)
|on Nov 21, 2000 at 22:03 UTC||Need Help??|
There is one important things to note about foreach and while loops, namely the localization of the loop variable.
The foreach loop will always localize its loop variable (That is $_ unless one is spesified). This can easily be verified:
This will print
Inside loop: $_ =  Inside loop: $_ =  Inside loop: $_ =  Outside loop: $_ = The while loop however, does not localize anything. This can be seen from the following example
If <FH> produces three lines containing the digits 1, 2 and 3 the output will be
Inside loop: $_ =  Inside loop: $_ =  Inside loop: $_ =  Outside loop: $_ = It will also produce a warning if you remembered to turn on the -w flag. Why the warning you might ask. The reason is because the <FH> will return undef when it has reached the end of the file, and $_ is assigned this undef. And as we all know, perl will warn us if we use an undefined value (if the -w flag is used).
So then, what is it that happens in your program ? First, let's just simplify it a little bit (concentrating on the first foreach loop):
Now, what happens is that the foreach loop creates spesial references into the @test_array. (Spesial in the sense that when you change $_, you also change the corresponding element in the @test_array)
The next line should then print out the value of $_, which in your example would be "Element1". Then we open ourself, and loop over each line in the file. The while (<IN>) construct implicitply assigns the $_ without first localizing it. Thus we actually change the elements of the array @test_array.
If you instead had used a foreach loop to iterate over the file, this problem would not have occured, because of the fact that it would have localized the $_ variable for you. Or you could localize $_ yourself by writing local $_. Another possible solution is to use lexical variables both in the foreach loop and in the while loop
(The defined test isn't really necessary in newer perls, but I like to be explicit here).
"But", I hear you complain, "my while loop is in a different function, a completly new scope". Well, that is correct if you are talking about lexical scoping (variables declared with the my keyword are lexical variables). However, $_ is a dynamically scoped variable (this fact you can't change, you can't declare my $_. Here is a good tutorial explaining the difference between a lexical scope and a dynamic scope.) However, since $_ is dynamically scoped, it will live on in the new function only to be assigned by the while loop.
I hope this shed some light on the problem at hand.