Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, How could I make a conditional loop more elegant? I want to do one set of statements if it meets the first condition but if it meets the second condition, I want to loop thru that first set of statements within a while loop. See pseudo code below. I want to re-write something like the following, so that I don't have to repeat the set of statements twice in my code.
if condition1 { stmt1 stmt2 ... stmt30 } elsif condition2 { while innercondition1 { stmt1 stmt2 ... stmt30 } }
I was hoping to avoid a subroutine so I wouldn't have to worry about scoping and references. Maybe something like a goto? I don't know if that's barking up the wrong tree... Thanks in advance for your help, Anna anna@water.ca.gov

Replies are listed 'Best First'.
Re: conditional loop
by sauoq (Abbot) on Aug 26, 2002 at 23:31 UTC
    Use a subroutine.
    if condition1 { mysub(); } elsif condition2 { while innercondition1 { mysub(); } } sub mysub { stmt1 stmt2 ... stmt30 }
    -sauoq
    "My two cents aren't worth a dime.";
    
Re: conditional loop
by Aristotle (Chancellor) on Aug 27, 2002 at 00:40 UTC
    The naked block is a good starting point, but I wouldn't use redo. This is the way to evaluate the conditions as few times as possible, and also in the exact same order as your own code:
    { last unless (my $once = $condition1) and $condition2; while(1) { # ... # ... last if $once or not $condition3; } }

    Careful about the order of checks. Note that you might skip preserving the state in $once so long as $condition1 wouldn't change during an iteration of the loop and checking it doesn't have any side effects. However, you will have to duplicate the code at the bottom of the loop, so I believe the above form is still clearer in intent. It also has the benefit that it evaluates the expression only once.

    Update: (Duh me.) So long as your statement 1..30 don't need next/last, you can and probably should use a do while:

    { last unless (my $once = $condition1) and $condition2; do { # ... # ... } while not $once and $condition3; }

    Makeshifts last the longest.

Re: conditional loop
by BrowserUk (Patriarch) on Aug 26, 2002 at 23:33 UTC

    Depending on where your conditions are set and change the following could be a way to do it.

    sub stuff statement 1 statement 2 statement 3 .... } if(cond1) { stuff(); } elsif (cond2) { stuff() while (innercond); }

    What's this about a "crooked mitre"? I'm good at woodwork!
Re: conditional loop
by Django (Pilgrim) on Aug 27, 2002 at 00:02 UTC
    You could also use a bare block instead of a loop:
    { stmt1..30 if c1 || ( c2 && c3 ) ; redo if ( c2 && c3 ) ; }
Re: conditional loop
by the pusher robot (Monk) on Aug 26, 2002 at 23:32 UTC
    while (condition1 || condition2 && condition3) { ... last if condition1; }
    ...should work (assuming conditions 1 & 2 don't change during the loop), although there may be a better way to do it. (condition3 == your innercondition)
Re: conditional loop
by Anonymous Monk on Aug 27, 2002 at 22:01 UTC
    while( (condition1 && (0&&$. .. 0&&$.) < 2) || (condition2&&innercondition1 ){ stmt1 stmt2 ... stmt30 }
      Ugh. You have to look at least twice to catch what that's doing and a novice will be hopelessly confused. Life is not a JAPH contest. Also, it evaluates all conditions over and over in case it does loop.

      Makeshifts last the longest.