The linked article definitely gets it right about Donald Knuth's N+1/2 Loops. Expressed in C/C++/Java:
for (;;) {
get next element;
if (at the end) break;
process the element;
}
This is useful for reading lines or characters from a file, testing if you've reached EOF, and then processing it. I'm so used to seeing the pattern for(;;)..if(..)break;
appear that it's idiomatic to me. (Before I had read the Knuth article, reprinted in the book Literate Programming, this one used to be a "wtf?".)
Knuth suggested the keywords loop/while/repeat
:
loop:
S;
while C:
T;
repeat
Where S
and T
are place holders for a series of zero or more statements, and C
is a boolean condition. If there was no S
statement then it would be a while loop, and if there was no T
statement then it would be a do loop.
This construct itself could be generalized by allowing zero or more while C
clauses, making it perfect for expressing infinite loops and then some rarer conditions that would need two checks.
In the same article, Knuth suggested a signaling mechanism that would be a local version of throwing/catching exceptions (as an alternative to using goto).
For me? I wish Java supported tail-call optimization, so that I could express any general control structure as needed.
Update: I forgot to mention that many C/C++/Java programmers get around this one by using an embedded assignment in the condition of the while
:
while ((c = getc(f)) != -1) {
T;
}
Using the terms from Knuth's construct, this is allowable when S
and C
can be combined into a single expression. Some people hate to see the embedded assignment above, while others hate to see the break
in the for (;;)
above. But when S
and C
cannot be combined, such as when S
has multiple statements, the for (;;)
is the only alternative without repeating code. The other alternative is to simply duplicate the S
code:
S;
while (C) {
T;
S;
}
Knuth's loop/while/repeat
alternative seems much better.