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

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.

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

      That use case is completely sensible. Your original was a string overwritten with a count and reminded me of the awful code I've had to deal with over the years where there is one $i or $output and friends shared around huge scopes or even more than one script, concatted or overwritten willy nilly. Your use case in a small scope seems totally kosher though it's outside my style or sensibility.

      I can remember that long time (say: 30 or more years) ago, I also wrote loops like that.

      But now that you mention it, and thinking about it, I notice always write those kind of loops like:

      my $interesting_index= 'not existing'; for ($i=1; $i<=10; ++$i) { next unless &condition($i); $interesting_index= $i; last; } # spit an error if $interesting_index is still 'not existing'

      The reason behind this is simply that your loop might not have found a valid value.


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
        There are many variants of how to do this. My inclination might be:
        my $interesting_index; my $i = 0; while (!defined($interesting_index) and $i++ <= 10) { $interesting_index = $i if condition($i); } # spit an error if $interesting_index is still 'not defined'
        If the purpose of the loop is to find an index, then I would try to make that fact prominent at the start of the loop. That way you don't have to read the body of the code to figure out the purpose/intent.

        In Perl often there are other ways to do something similar to this functionality with the various List::utils. My Perl code rarely uses any $i subscripts.

        update: maybe I have an "off by one" error in original post. I think it is also possible to use the C style loop:

        for (my $i=1; !defined($interesting_index) and $i<=10; $i++){}
      I have made this mistake in the past. I now usually avoid the issue by using a function such as "first_index" in List::MoreUtils.
      Bill