in reply to loop surprise

Hello morgon,

From perlsyn#Foreach-Loops (first paragraph):

The foreach loop iterates over a normal list value and sets the scalar 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 localization occurs only in a foreach loop.

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: loop surprise
by morgon (Priest) on Apr 03, 2018 at 13:44 UTC
    Ok, that explains it, but I don't quite get the rationale for doing it this way...

    If I wanted a localized variable I write the loop as "for my $j (...)".

    If I explicitly use "for $i" I make clear my intention of using a previously introduced variable.

    Why perl then insists on knowing better and localizing it is counter-intuitive to me and at the moment I don't see any reason why it should be implemented like that (but there probably is one)...

      Hi morgon,

      I wouldn't say it's that Perl "knows better" so much as that it's a convenience for being able to modify the data you're iterating over.

      Note that, because it's only a foreach loop that acts this way, and for is this context is just an alias for the same thing, if you want the behavior you were expecting you can use the 3-arg form of a for loop:

      use strict; my $i = "whatever"; for ($i = 1; $i <= 10; $i++) { last if $i == 7; } print "$i\n"; # prints "7" instead
      And believe it or not, you could even make it a 3-arg foreach loop (which is kinda counter-intuitive, but again, "for" and "foreach" are interchangeable):
      use strict; my $i = "whatever"; foreach ($i = 1; $i <= 10; $i++) { last if $i == 7; } print "$i\n"; # still prints "7"
      say  substr+lc crypt(qw $i3 SI$),4,5
        Very cool.

        I was aware that for and foreach are synonyms, but that the 3-arg from of for behaves differently from the list-form with respect to variable localization is entirely new to me - and again unexpected...

        Why would these two forms not use the same logic wrt variable localization ... beyond me...

        Oh well, just one more wart I guess...

      > get the rationale for doing it this

      This was often discussed already, have a look into the archives if you want more details.°

      IIRC it's because this behaviour of localizing the loop var is older (read Perl4) than lexicals.

      Rule of thumb: never try to reuse an outer var as loop var in foreach... see also PBP advice to always for my $x (...) .

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      °) it leads to very confusing results if the loop creates subs closing over the loopvar.