1

Suppose I have this loop:

boolean modified = true;
while(modified == true){
    modified = false;
    for (Object o : objectList){
        // do logic
        if (... condition...){
            modified = true;
        }
    }
}

I don't like that I initially have to declare the modified variable as true. The loop should terminate if in a round no more modifications have occured.

Andrew
  • 95
  • 2
  • 12
  • In Java the `break` keyword serves this purpose, although its use is controversial, as it has a definite "procedural" smell to it, and obscures the control flow. What you just wrote is quite common, and its common use makes its purpose clear to the reader. – MikaelF Oct 13 '19 at 15:20
  • @JaredFarrish I think what OP was looking for is a way of omitting the declaration of `modified`. – MikaelF Oct 13 '19 at 15:21
  • This question is lacking a language tag; solutions may differ according to language (Java vs C++ vs Javascript). – MikaelF Oct 13 '19 at 15:24
  • @JaredFarrish I see your point; however, at least in C++ and Java, this [won't](https://stackoverflow.com/questions/18541304/use-variables-declared-inside-do-while-loop-in-the-condition) [work](https://stackoverflow.com/questions/16533859/accessing-a-variable-from-inside-a-do-while-loop). In these languages, `modified` has to be *declared* outside the loop, but *assigned* a value inside the loop. – MikaelF Oct 13 '19 at 15:30
  • I edited the question. The modified attribute comes from a nested loop. So breaking is not possible. – Andrew Oct 13 '19 at 15:38
  • @Serberker It is in fact possible in Java, using [loop labels](https://stackoverflow.com/questions/3821827/loop-in-java-code-what-is-this-and-why-does-it-compile). As previously stated, this usage is not recommended in Java, as it tends to obscure the control flow. It is however necessary in some algorithms. – MikaelF Oct 13 '19 at 15:40

2 Answers2

5

If I would have been you, I would write the logic like below.

boolean modified = true;
while (modified) {
    for (Object o : objectList){
        // do logic
        modified = (modified && condition);
    }
}
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
0

Here's a construct that will keep modified within the loop's scope, but still requires a declaration:

for (bool modified = false; modified; ) {
    modified = false;
    for (Object o : objectList) {
        modified |= condition; 
        /* If "condition" involves heavy computation, prefer the type of
           condition-checking in @Sazzad's answer, as this will not
           short-circuit to "true" if "modified" is already true. */
    }
}

Alternately, use a while loop with a label (although labels don't really belong to the OO style):

outer:
while(true) {
    for (Object o : objectList) {
        //do stuff
    }
    if(objectList.stream().anyMatch(/* condition predicate */)) {
        break outer;
    }
}

This will work with however many levels of nesting you have.

Here's a third solution using a do-while loop:

do {
    for (Object o : objectList) {
        //do stuff    
    }
} while (objectList.stream.anyMatch(/* predicate */));

Depending on what your condition looks like, you can make the check pretty obvious using a method reference:

objectList.stream().anyMatch(this::condition);
MikaelF
  • 3,518
  • 4
  • 20
  • 33