http://qs321.pair.com?node_id=1212259


in reply to Re^2: loop surprise
in thread loop surprise

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

Replies are listed 'Best First'.
Re^4: loop surprise
by morgon (Priest) on Apr 03, 2018 at 18:00 UTC
    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...

      The localization behavior, in my view, is expected and a benefit, not a wart. The only surprise was the localization was transparent and legal, but again, to me, I never would have found out on my own because repurposing variables like that is code smell.

        Maybe it is a code smell...

        But what I was trying to do is to find the smallest number in a certain range satisfying some condition and then go on using that found value.

        Doing it like

        my $i; for $i (1..10) { last if &condition($i); } &do_more_stuff_with_the_value_found($i);
        Looked (at the time) to be a straightforward solution and I was suprised that it did not work.

        This is just for explaining where this comes from (I am not a really good programmer I am afraid...)

        And even accepting that this is not the way to do it (there are of course many other ways), it is neverthless surprising that this actually does work:

        my $i; for ($i=1; $i<=10; $i) { last if &condition($i); } &do_more_stuff_with_the_value_found($i);
        This is to my eyes at least an inconsistency (and thus a wart). But whatever, this is how it was, is and will be...