Tuesday, July 31, 2007

Control Loops

Part of my work is programming; as such, I occasionally run into a limitation of a language. Today, the language is C/C++ and the limitation is control loops.

Here's my beef:
If I want to make a loop where I do a complicated test every time I go around the loop, there are two options open to me:

First, I can use a while loop, and duplicate code.

foo()
{
a = xyzzy();
b = zxc();
c = bop();
while (a-b>c){
gazonk(a, b, c);
a = xyzzy();
b = zxc();
c = bop();
}
}
This is ugly. It demonstrates the problem, however. If xyzzy(), zxc(), and bop() are functions that are not fast to execute, saving them to a variable is imperative to performance. They can't simply be combined into a single true/false variable because gazonk needs them separately.

The second option is that I can embed my other calls in a function with references, and use a for loop.
foo()
{
for (bar(a, b, c); a-b>c; bar(a, b, c)){
gazonk(a, b, c);
}
}
bar(&a, &b, &c)
{
a = xyzzy();
b = zxc();
c = bop();
}


This one's not much better. It requires an extra function call per loop, and still requires a duplicate function call. I'd rather have a structure where I can always perform the same "init code" before the test. An extended do-while loop, if you will. Here's an example:
foo()
{
do{
a = xyzzy();
b = zxc();
c = bop();
} while (a-b>c){
gazonk(a, b, c);
}
}

It could be used with a for loop as well; for loops could be extended into a do-for loop.
foo()
{
do{
a = xyzzy();
b = zxc();
c = bop();
} for (int i=0; a-b>c; i++) {
gazonk(a, b, c, i);
}
}

The most interesting thing about this is that there is no good reason that this structure shouldn't exist. It would implement perfectly well in assembly. The loop test would simply not be the loop entry point.
So where's my do-for loop? And do any other languages implement this very useful and frequently used structure