Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Perl style question: loops with postcondition

by IlyaM (Parson)
on Jun 28, 2002 at 09:15 UTC ( [id://177971]=perlquestion: print w/replies, xml ) Need Help??

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

I've seen three common forms used to implement loops with post-conditions:
  1. do { ... } while($condition)
  2. while(1) { ... last unless $condition; }
  3. LOOP: ... goto LOOP if $condition;
I'm curious what form is the most popular. I understand that perl is about TMTOWTDI so I don't ask which is the form is the best. I merely interested what preferences have Perl monks and why.

--
Ilya Martynov (http://martynov.org/)

Replies are listed 'Best First'.
Re: Perl style question: loops with postcondition
by Zaxo (Archbishop) on Jun 28, 2002 at 10:20 UTC

    Choose the form which fits the situation, and makes linguistic sense. It's not a popularity contest.

    do () while $condition; suggests the condition is temporary and that the bracketed code labors to make it go away.

    while (1) { {}; last unless $condition} reads as if the loop is the thing, and that failure of $condition is exceptional.

    LOOP:{ {}; goto LOOP if $condition} shouts "I don't care what anybody thinks, I'm looping!" ;-)

    There are many WTDI you omitted, and different programmers will say thinngs differently. TIMTOWTDI, but also DSFDF.

    After Compline,
    Zaxo

Re: Perl style question: loops with postcondition
by djantzen (Priest) on Jun 28, 2002 at 10:12 UTC

    Depends on the purpose of the code.

    I think the first is the cleanest way for simple loops of this sort, and I'm reticent to use infinite loops for anything other than long running processes. Setting up a deliberately short-circuited infinite loop for this kind of purpose can work against intelligibility IMO. Labels I use semi-frequently but only in nested loops and switches.

    Here's some fun code though:

    use Experimental::Exception; do { ..... } while ( try { $thingy->doSomething(); } catch SomeException => sub { return undef; }; )
    Update: slight code change to better reflect the nature of the question.

Re: Perl style question: loops with postcondition
by broquaint (Abbot) on Jun 28, 2002 at 10:05 UTC
    In general I use the second form which I guess is because of my C influenced learning. But having given it a second of thought I may switch to using a continue block as it's seems the most natural e.g
    while(1) { ... } continue { last unless $condition; }
    There's also the issue that the first form is guaranteed to iterate through the loop at least once which isn't always ideal.
    HTH

    _________
    broquaint

Re: Perl style question: loops with postcondition
by aersoy (Scribe) on Jun 28, 2002 at 09:49 UTC

    Hello,

    I myself find 1 and 2 to be easier to read and understand than 3. The reasoning is simple, I try to make grammatically correct English sentences as much as possible. And when it comes to decide between 1 and 2, I would go for 1, as it actually makes use of the parantheses of while, as opposed to 2. (Disclaimer: but that's just me.)

    --
    Alper Ersoy

Re: Perl style question: loops with postcondition
by bronto (Priest) on Jun 28, 2002 at 12:32 UTC

    First of all, I don't like the third at all :-).

    The first is fine, but it goes a little against my sense of KISS: it is perfectly clear to me what it would do, but... will it be for others that may read my code?

    The second... well, I like a different approach, since I tend to use obviuous while test conditions only if I can't do without (for example, using the shell: while true ; do ...; done).

    My approach is similar to the second one, but slightly different in syntax:

    MY_BLOCK: { # do whatever you like # inside here and, if appropriate, set $condition redo MY_BLOCK unless $condition ; }

    This way I achieve my goal without using trivial cycle conditions and, hopefully, being more readable to others.

    Just my 2 cents (of Euro)

    --bronto

    # Another Perl edition of a song:
    # The End, by The Beatles
    END {
      $you->take($love) eq $you->made($love) ;
    }

Re: Perl style question: loops with postcondition
by kodo (Hermit) on Jun 28, 2002 at 10:48 UTC
    For me Nr.1 (
    do { ... } while($condition)
    is the most (logical | easy to read) one. But I also like Nr.2
    I don't like Nr.3 because I learned that goto: "It scans outward from your current location for the indicated label." (by larry wall) which decreases performance and just look weird (remembers me on basic and dos-batches...) to me...

    giant
      giant said:

      I don't like Nr.3 because I learned that goto: "It scans outward from your current location for the indicated label." (by larry wall) which decreases performance and just look weird (remembers me on basic and dos-batches...) to me...

      I'll give you the basic and dos parts, but I'm fairly sure that "scans outward" would only apply if you're using the goto EXPR form, rather than a goto LABEL where the label is explicit.

      For the goto LABEL form, the location of LABEL has to be resolved at compile time, so it's probably not very costly.

      Check out Programming Perl, 3rd Edition, page 126.
      --
      Mike

Re: Perl style question: loops with postcondition
by Juerd (Abbot) on Jun 28, 2002 at 13:49 UTC

    This is what I'd do:

    { ... redo if $condition; }
    Next best thing is do while, imho.

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.
    

Re: Perl style question: loops with postcondition
by Aristotle (Chancellor) on Jun 28, 2002 at 15:49 UTC

    A tricky question, and one that usually has me trying to avoid the need for a post condition in the first place.

    LOOP: .. goto LOOP if is completely out of the question ever since I grew out of BASIC. :)

    redo if uses an unnamed block that to me signals "short term lexical variables required for the next couple of lines", not "postcondition loop here" when I'm reading the code.

    continue has the disadvantage of a massive performance hit, so I only resort to it when I need its special property that the continue-block is executed regardless of where or how the main loop's body was exited. Which so far, was never.

    do while would be the natural way to go about it, but has the disadvantage that you cannot use next and co in the (non)loop body. It's ok for short loops though.

    Thus, while(1) last if is what I'd do most of the time.

    However, these calls are just mine; I can see that someone else might disagree with them. Basically, since there's no "real"/"official" postcondition loop construct in Perl, it is mostly up to you. The only thing I will "insist" on is to immediately forget the goto form - but I guess you knew that anyway.

    Makeshifts last the longest.

Re: Perl style question: loops with postcondition
by mpeppler (Vicar) on Jun 28, 2002 at 15:59 UTC
    I tend to use do { ...} while();

    But keep in mind that next/last don't work as one might expect (at least for those of us who learnt C first, and perl later :-)

    Michael

Re: Perl style question: loops with postcondition
by Stegalex (Chaplain) on Jun 28, 2002 at 14:33 UTC
    Serious question:
    Is there a legitimate need for goto? If not, shouldn't this language construct be deprecated?

    P.S. No offense to fans of the venerable 'goto'.

    ~~~~~~~~~~~~~~~
    I like chicken.

      YES! Mostly, we have goto LABEL and goto EXPR for the sake of completeness. People expect them to be there, and there they are. This is useful.

      But much more importantly, goto can be used to eliminate / substitute one subroutine call for another. For example, suppose you have a subroutine which uses caller. Now, what if that sub is called by and AUTOLOAD in the same package. You've borked your caller. But, if you goto to the subroutine, then even caller can't figure out that AUTOLOAD itercepted the call.

      Cheers,
      Erik

      Light a man a fire, he's warm for a day. Catch a man on fire, and he's warm for the rest of his life. - Terry Pratchet

      I think that's like "The -w switch is not mandatory." If you know, what you do, it can be (in a very strange and unimaginable situation) usefull to have goto.
        "unimaginable situation" is of course nonsense, as erik wrote about AUTOLOAD i remembered even i had used goto &$subref for nested AUTOLOAD routines in a module that exports an AUTOLOAD routine to the use()ing package but gives a possibility to specify a sub-reference that handles function that could not be found by the current AUTOLOAD routine.
Re: Perl style question: loops with postcondition
by Anonymous Monk on Jun 28, 2002 at 19:40 UTC
    My viewpoint is to use as high-level a construct as is posible. High-level constucts: for(;;), foreach(), while(), do{}while() are easily recognized and the reader can concentrate on what the loop does. Use lower level constructs when the high-level constructs don't give you what you need.

    for(), foreach() and while() satisfy 99% of my needs, and I rarely use any of the forms you list. do{}while() is appealing because it runs at least once, so it seems useful when a loop needs an initialization. However, things are rarely that simple, and usually the first pass will be quite difference, especially once you provide handling for NULL input: an empty array, an undef array, no such file, etc. So I wind up refactoring some of the code into a subroutine and using an ordinary loop, perhaps with some initialization.

    The 'last if/unless $condition' form is usefull when you need to exist in the middle of a loop. while(){}continue{} is good, if it can isolate the actions which follow the condition detection point, but that doesn't always work, and sometimes there are two or more related conditions, eg: file does not exist, file is not readable, file is empty, end of file.

    As an aside, sometimes I have wound up with this form when, during development, I want to do some debugging after the condition point, which gets removed prior to the final release. Rather than re-work the whole loop, the clumsier code gets left behind.

    Other than the form used in AUTOLOAD routines, GOTO is hardly ever needed. Since it is clumsy and reveals nothing about the intention of the jump, it is best to avoid GOTO unless there is no other way to do what you want. Very rarely, using loop and condition constructs becomes so clumsy that using a GOTO allows the rest to be simplified greatly. Most of the time, a last, next or redo can do the job ... they are simply synonyms for GOTO with more information about the intent. I don't think I've used a GOTO since packing away my TRS-80, but I have seen code that called for it.

    TomDLux

Re: Perl style question: loops with postcondition
by hsmyers (Canon) on Jun 28, 2002 at 20:04 UTC

    I'd go with do { } while($condition); since the other two violate some of my own pet peeves. I don't like invariants in place of conditions-- too easy for me to miss let alone the poor fool who is maintaining my code. If I need a GOTO fix, I'll code in assembler. Besides the first construct has fewer semantic elements to screw up!

    –hsm

    "Never try to teach a pig to sing…it wastes your time and it annoys the pig."
Re: Perl style question: loops with postcondition
by Popcorn Dave (Abbot) on Jun 28, 2002 at 20:01 UTC
    I'm not so sure if it's which is most popular as much as it depends on what you're trying to do.

    As a lot have said, the do-while loop is popular, but it is different in execution from the while loop.

    As it was explained to me in a beginning perl class, you need to simply keep in mind that a while checks the condition initially and may not execute. A do-while executes at least once before the condition is checked.

    As far as the LOOP: variant (shudder...) that seems to be more of a throwback to the old days of BASIC, but that's just my opinion. : )

    Some people fall from grace. I prefer a running start...

Re: Perl style question: loops with postcondition
by december (Pilgrim) on Jun 29, 2002 at 14:55 UTC

    Most popular... oh dear.

    Well, with respect to speed, I don't think it matters. When the code is executed in machine-language, you know, run time compilation (or better, interpretation), the instructions will be pretty much the same; same amount of conditional jumps and conditional code. So none of these will be faster or slower, I think.

    Security isn't relevant directly, here.

    So what's left, is, well, personal choice. Readability of the code. Choose what looks best to you, the option that makes things most clear while just scanning the code. I know this probably isn't really what you want to hear, but, how can I determine what's most clear in _your_ eyes?

    If you really need an answer, well, I personally think I would prefer (1) in most situations.

Re: Perl style question: loops with postcondition
by braughing (Sexton) on Jun 30, 2002 at 01:07 UTC
    TomDLux mentions for (;$condition;) {} which has several advantages - it explicitly signals a 'postcondition loop' (or whatever other kind of loop) right at the beginning, it has its own scope and allows last etc, and most importantly it is flexible. It's pretty ugly though.
Re: Perl style question: loops with postcondition
by Nitrox (Chaplain) on Jul 22, 2002 at 23:37 UTC
    What about
    while($condition) {...}
    -Nitrox
      That one's not a post-condition, though... in the original post, all the examples will execute the loop at least once, but while($condition){...} has the possibility of never executing the loop (if $condition is initially false).

      -- Mike

      --
      just,my${.02}

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://177971]
Approved by kappa
Front-paged by wil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2024-04-20 00:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found