Question

Occasionally - but recurringly - I face the following loop pattern problem:

CodeSnippet1
DO WHILE LoopCondition   //LoopCondition depends on some pre-calculation from CodeSnippet1
    CodeSnippet2         //CodeSnippet2 relies on LoopConditon=true
    CodeSnippet1
LOOP

The problem I see here is the code duplication of CodeSnippet1.

At the first glance, it seems like I should move the condition to the end:

DO
    CodeSnippet1
    CodeSnippet2
LOOP WHILE LoopCondition

This won't work since CodeSnippet2 assumes LoopCondition=true. The next try would be:

DO
    CodeSnippet1
    IF LoopCondition THEN CodeSnippet2
LOOP WHILE LoopCondition

Again far from elegant.

In C-like programming languages, one can do the following:

while(complicated-expression-containing-CodeSnippet1-and-LoopCondition) {
    CodeSnippet2
}

But

a) this can get difficult to understand and

b) not every programming language can perform arbitrary calculations, especially variable assigments, during evaluation of some loop condition.

Recently, I came up with the following way:

DO //endless loop
    CodeSnippet1

    IF NOT LoopCondition THEN EXIT LOOP

    CodeSnippet2
LOOP 

This tends to lead structured programming with loops ad absurdum / reminds me a bit of GoTo programming style.

My Question:

Are there (more or less) objective reasons to prefer one of the mentioned loop programming styles over the others?

EDIT:

I know in many occasions CodeSnippet1 together with LoopCondition can be encapsulated in a function returning the loop condition, and we're done. I agree with that. But this does not hold in general. Above in b) I tried to hint at "variable assignments". Here in detail:

My favourite minimal but real-world example: Using a BufferedReader in Java:

line = bufferedReader.readLine();
while(line != null) {
    //CodeSnippet2
    line = bufferedReader.readLine();
}

vs.

while((line = bufferedReader.readLine()) != null) {
    //CodeSnippet2
}

Both variants are not satisfying. Factoring out (line = bufferedReader.readLine()) != null into a function that returns a boolean has one new problem: How to retrieve line? Using a global variable / class member just for this purpose?

Was it helpful?

Solution

Congratulations! You've just reinvented Ada's looping structure. Jean Ichbiah probably reinvented someone else's prior art.

This is de facto possible in a lot of languages, where you can create endless loops with programmed exits. For example, in Python:

while True:
    do_stuff()
    if not loop_continues:
       break
    do_more_stuff()

The reason so many languages have a test-at-top loop (while), a test-at-bottom loop (do until), and a counting/iterating loop (for) is that those are the most common patterns, and most likely to be needed. But with modern break ("get me out of this loop!") and continue ("we're ready for the next iteration!") options, there really aren't nearly as many needs for bespoke loop syntax to cover all the options. Python, e.g., does with just for and while variants.

The early-exit (break) and early-continue (continue) operations are well-structured, with only a few well-designed places they can take you (namely to the bottom/exit of the loop, or to the top of the loop). They are not the "I may jump to pretty much any line!" wildcards of the olden GOTO days, and so they can get you (and whatever optimizer your compiler toolchain is using) into many fewer sticky situations.

Given that we now have (pretty much irrespective of language used) good structured means to test and manage loop behavior, I'm unclear why anyone would have a strong preference. Test where it makes sense for the algorithm involved: At the top, at the bottom, or some place in between.

OTHER TIPS

Because also of dovals comment:

Wrap codesnippet1 and the loopcondition in a function, because apparently the loopcondition is set by codesnippet1. Which then returns the loopcondition then you get:

DO WHILE CodeSnippet1AndLoopConditionFunction   
  CodeSnippet2    
LOOP

I was told in school that escaping a loop using GOTO or equivalent (such as "break" in C) is a bad style of programming. A school-approved way is to introduce a variable as a switch that once active will cause a loop to exit.

In C, this is a school-approved way to write a loop:

int bool=0;
int count=0;
while (count < 100 && bool==0){
    count++;
    if (count == 10){
        bool=1;
    }
}

This is not a school-approved way to write a loop:

int count=0;
while (count < 100){
    count++;
    if (count == 10){
        break;
    }
}

However, the non-school approved way uses a few bytes less of stack space (because one less integer is reserved for the program).

Licensed under: CC-BY-SA with attribution
scroll top