Consider the pseudo-procedure below:
--beg
if (condition_a)
condition_b = !condition_b;
while (condition_a and condition_b)
•••Do something that can mutate condition_a and/or condition_b•••
--end
condition_b
is an already existing condition that must be toggled (if condition_a
is true
) before the loop will even start.
condition_a
is tested twice which is "unnecessary". I want to remove the "unnecessary" test. [1][2]
I considered the following:
repeat-until
.condition_b
at the start of each loop iteration.All will lead to multiple setting of condition_b
which is also an O(n) test of the condition (worse than my original intention).
What other approach will you suggest?
[1] The use of "unnecessary" is completely subjective and it is actually the premise of this question. I feel like the first test can be avoided and the second test, which is the most significant one, should suffice.
[2] If you disagree with it being unnecessary, please prove your claim of its necessity.
The following would not execute the loop if either condition_a
is false, or condition_b
is true (before being toggled). As the condition is fully tested before the first iteration of the loop, we can move the loop's condition at the end of the loop's body:
if (condition_a) {
if (condition_b) {
condition_b = false
} else {
condition_b = true
do {
•••Do something that can mutate condition_a and/or condition_b•••
} while (condition_a and condition_b)
}
}
If you're OK with making an assignment inside a boolean expression, and you can rely on shortcircuit evaluation of &&
, you can shorten this to:
if (condition_a && (condition_b = !condition_b)) { // assignment
do {
•••Do something that can mutate condition_a and/or condition_b•••
} while (condition_a and condition_b)
}
condition_a
before the loop conditionIf you really wanted to force all to happen within the context of the loop, you'll need to add work to the loop's body, which will affect performance, and the state of condition_b
after the loop. For instance:
while (condition_a && (condition_b = !condition_b)) {
•••Do something that can mutate condition_a and/or condition_b•••
condition_b = !condition_b
}
Note how condition_b
is negated at the end of each iteration, so to counter the effect of the negation that happens in the loop-condition. But if condition_a
becomes false
inside the loop's processing, then condition_b
will exit the loop with a negated value. If this is irrelevant to the code that follows, it can be left like that, but if not, you need to guard that change to condition_b
:
while (condition_a && (condition_b = !condition_b)) {
•••Do something that can mutate condition_a and/or condition_b•••
if (condition_a) {
condition_b = !condition_b
}
}
This does not look that elegant anymore, and besides the repeated negation of condition_b
, it now also evaluates condition_a
more than in your original code (once the loop makes at least one iteration).