in reply to Re: Last undefines a for loop's itererator?
in thread Last undefines a for loop's itererator?

for $i ( 1 .. $foo ) { last if bar($i); } print $i;
Is there any good idiom that uses foreach, but yet still lets me access the variables afterwards? (And no, the chunk is far too small for a subroutine.)
use warnings; use strict; my $i = sub { for my $i (1..5) { return($i) if ($i == 4); } }->(); print $i;

If it doesn't work under warnings and strict, there is probably a good reason for that. IMO, if you want to access the loop variable outside the loop, you should declare a separate variable and set it explicitly before you drop out of the loop.

If what you really want is a loop that behaves like a subroutine, why not just write it as such?

Replies are listed 'Best First'.
Re^3: no chunk is too small
by kaif (Friar) on Nov 13, 2005 at 23:17 UTC
    If it doesn't work under warnings and strict, there is probably a good reason for that. IMO, if you want to access the loop variable outside the loop, you should declare a separate variable and set it explicitly before you drop out of the loop.
    It does work fine under warnings and strict, if you don't declare your variable in the conditions on the for(..) loop. It has always seemed weird to me to write code like
    my $iold; for my $i ( 1 .. $foo ) { if( bar($i) ) { $iold = $i; last; } }
    Doesn't it just seem like a waste of variables? You're clearly using $i and $iold for the same purpose.

    As for why it isn't a subroutine, perhaps because I like this code all in one place. Shrug.

      It has always seemed weird to me to write code like

        my $iold;
        for my $i ( 1 .. $foo ) {
          if( bar($i) ) {
            $iold = $i;
            last;
          }
        }
      

      Doesn't it just seem like a waste of variables? You're clearly using $i and $iold for the same purpose.

      No, you're using $i as a loop variable and $iold as the return value of the loop. Variables are cheap. Using them to buy clarity is a "good deal"™.

      As for why it isn't a subroutine, perhaps because I like this code all in one place. Shrug.

      This code is all in one place. It is just a loop with a return value. Read carefully.

      my $iold = sub { for my $i ( 1 .. $foo ) { if( bar($i) ) { return($i); } } }->(); # calls this anonymous sub (setting $iold)

      Note that it takes the same number of lines to set an external (to the loop) value and last; as it does to define your loop as an anonymous sub and return($i);

      This also gets you the benefit that if the loop gets more complicated or needs to be reuse, refactoring just means yanking it verbatim and making it a named sub because nothing inside of it relies on lexical scope. (Yeah, you have to put any parameters in the ->($var1, $var2); part for this to scale.)

      I agree. If the variable used as the loop variable is a pre-existing variable and my is not used, it should not be localised and retain is final value after the loop body.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Do you want to tell even more people “don’t forget to localise $_” than already get bitten because while(<>) does not localise it?

        I suppose there could be an exception either for $_ or for all global variables, but wouldn’t that be overdoing it a little?

        Makeshifts last the longest.