Assuming I have this pseudo-code:
bool conditionA = executeStepA();
if (conditionA){
bool conditionB = executeStepB();
if (conditionB){
bool conditionC = executeStepC();
if (conditionC){
...
}
}
}
executeThisFunctionInAnyCase();
Functions executeStepX
should be executed if and only if the previous succeed.
In any case, the executeThisFunctionInAnyCase
function should be called at the end.
I'm a newbie in programming, so sorry for the very basic question: is there a way (in C/C++ for example) to avoid that long if
chain producing that sort of "pyramid of code", at the expense of the code legibility?
I know that if we could skip the executeThisFunctionInAnyCase
function call, the code could be simplified as:
bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;
But the constraint is the executeThisFunctionInAnyCase
function call.
Could the break
statement be used in some way?
Just use an additional function to get your second version to work:
Using either deeply nested ifs (your first variant) or the desire to break out of "part of a function" usually means you do need an extra function.
There is actually a way to defer actions in C++: making use of an object's destructor.
Assuming that you have access to C++11:
And then using that utility:
Maybe not the best solution but you can put your statements in a
do .. while (0)
loop and usebreak
statements instead ofreturn
.There's a nice technique which doesn't need an additional wrapper function with the return statements (the method prescribed by Itjax). It makes use of a do
while(0)
pseudo-loop. Thewhile (0)
ensures that it is actually not a loop but executed only once. However, the loop syntax allows the use of the break statement.You could also do this:
This way you have a minimal linear growth size, +1 line per call, and it's easily maintenable.
EDIT: (Thanks @Unda) Not a big fan because you loose visibility IMO :
You just do this..
99 times of 100, this is the only way to do it.
Never, ever, ever try to do something "tricky" in computer code.
By the way, I'm pretty sure the following is the actual solution you had in mind...
The continue statement is critical in algorithmic programming. (Much as, the goto statement is critical in algorithmic programming.)
In many programming languages you can do this:
(Note first of all: naked blocks like that example are a critical and important part of writing beautiful code, particularly if you are dealing with "algorithmic" programming.)
Again, that's exactly what you had in your head, right? And that's the beautiful way to write it, so you have good instincts.
However, tragically, in the current version of objective-c (Aside - I don't know about Swift, sorry) there is a risible feature where it checks if the enclosing block is a loop.
Here's how you get around that...
So don't forget that ..
do { } while(false);
just means "do this block once".
ie, there is utterly no difference between writing
do{}while(false);
and simply writing{}
.This now works perfectly as you wanted...here's the output...
So, it's possible that's how you see the algorithm in your head. You should always try to write what's in your head. ( Particularly if you are not sober, because that's when the pretty comes out! :) )
In "algorithmic" projects where this happens a lot, in objective-c, we always have a macro like...
... so then you can do this ...
There are two points:
a, even though it's stupid that objective-c checks the type of block a continue statement is in, it's troubling to "fight that". So it's a tough decision.
b, there's the question should you indent, in the example, that block? I lose sleep over questions like that, so I can't advise.
Hope it helps.