P is for Practical | |
PerlMonks |
Re: What Is Going On Here ?????by autark (Friar) |
on Nov 21, 2000 at 22:03 UTC ( [id://42740]=note: print w/replies, xml ) | 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: $_ = [1] Inside loop: $_ = [2] Inside loop: $_ = [3] Outside loop: $_ = [42]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: $_ = [1] Inside loop: $_ = [2] Inside loop: $_ = [3] 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. Autark.
In Section
Seekers of Perl Wisdom
|
|