Uses for never-ending loops - loops

What are some uses of never-ending loops? They are usually bad news in programming, but is there ever a time when you want a loop to never end?

Infinite loops are only bad news when they are not intended or their use has unintended consequences. If you use them with intent there is no difference from any other classification of loop you might consider. However you will still end up breaking things despite intentional use. It is common to use this form when you want to access the iterator or index component after the loop has been terminated, for example:
index = 0;
result = null;
for (;;)
result = foo(index);
if (bar(result))
break;
index += result;
use(index, result);
Note that mutating data outside of the loop's scope may be very undesirable depending on the context, so whether or not this is a good use case really depends on the context. For another similar example, an actual iterator may be the object desired outside of the loop, but initializing it within the loop header would not allow access outside of the loop. An infinite loop would resolve this problem.
for (foo.iterator(); foo.hasNext(); ) {
use(foo.next());
}
keep_using(foo.next()); // throws an error
Additionally, infinite loops can in some cases improve readability, especially if there are many break conditions but they might not all derive from mutually exclusive units. For example, imagine we have the following:
for (;;) {
if (condition1)
break;
else if (condition2)
do_stuff();
else if (condition3)
break;
else
do_something();
}
This can be rewritten using the three components of a loop as:
for (condition = true; condition; iteration) {
if (condition1 || condition3)
condition = false;
else if (condition2)
do_stuff();
else
do_something();
}
However if we introduce a small amount of change (at least in terms of characters on the screen) to the original code:
for (;;) {
if (condition1);
break;
if (condition2);
do_stuff();
if (condition3);
break;
else
do_something();
}
The rewrite becomes this thing that requires us to lug around this extra variable:
for (condition = true; condition; iteration) {
if (condition1)
condition = false;
if (condition2) {
do_stuff();
condition = true;
}
if (condition3)
condition = false;
else {
do_something();
condition = true;
}
}
This can quickly become difficult to read and maintain as the loop body, and especially the complexity grows, for example if condition were actually many different conditions such as a || b || c < d || (e > f) && (a > f); or, the loop contained several nested loops. Though you might apply the same logic to other the original changed version.
Another readability related example involves verbose initialization, though admittedly not a very good use case:
for (more_long = some_ridiculously_long.initialization_statement.longer_than.Long_Long_Mans_Sakeru_gummy();
more_long < lots_of && more_long < break_conditions
maybe_even_an_update_that_hangs_at_ninety_nine_percent) {
...
}

Related

How does the break statement work in this function? [duplicate]

Can you break out of an if statement or is it going to cause crashes? I'm starting to acquaint myself with C, but this seems controversial. The first image is from a book on C
("Head First C") and the snippet shows code written by Harvard's CS classes staff. What is actually going on and has it something to do with C standards?
breaks don't break if statements.
On January 15, 1990, AT&T's long-distance telephone system crashed, and 60,000 people lost their phone service. The cause? A developer working on the C code used in the exchanges tried to use a break to break out of an if statement. But breaks don't break out of ifs. Instead, the program skipped an entire section of code and introduced a bug that interrupted 70 million phone calls over nine hours.
for (size = 0; size < HAY_MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
break;
// add hay to stack
haystack[size] = straw;
}
printf("\n");
break interacts solely with the closest enclosing loop or switch, whether it be a for, while or do .. while type. It is frequently referred to as a goto in disguise, as all loops in C can in fact be transformed into a set of conditional gotos:
for (A; B; C) D;
// translates to
A;
goto test;
loop: D;
iter: C;
test: if (B) goto loop;
end:
while (B) D; // Simply doesn't have A or C
do { D; } while (B); // Omits initial goto test
continue; // goto iter;
break; // goto end;
The difference is, continue and break interact with virtual labels automatically placed by the compiler. This is similar to what return does as you know it will always jump ahead in the program flow. Switches are slightly more complicated, generating arrays of labels and computed gotos, but the way break works with them is similar.
The programming error the notice refers to is misunderstanding break as interacting with an enclosing block rather than an enclosing loop. Consider:
for (A; B; C) {
D;
if (E) {
F;
if (G) break; // Incorrectly assumed to break if(E), breaks for()
H;
}
I;
}
J;
Someone thought, given such a piece of code, that G would cause a jump to I, but it jumps to J. The intended function would use if (!G) H; instead.
This is actually the conventional use of the break statement. If the break statement wasn't nested in an if block the for loop could only ever execute one time.
MSDN lists this as their example for the break statement.
As already mentioned that, break-statement works only with switches and loops. Here is another way to achieve what is being asked. I am reproducing
https://stackoverflow.com/a/257421/1188057 as nobody else mentioned it. It's just a trick involving the do-while loop.
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
Though I would prefer the use of goto-statement.
I think the question is a little bit fuzzy - for example, it can be interpreted as a question about best practices in programming loops with if inside. So, I'll try to answer this question with this particular interpretation.
If you have if inside a loop, then in most cases you'd like to know how the loop has ended - was it "broken" by the if or was it ended "naturally"? So, your sample code can be modified in this way:
bool intMaxFound = false;
for (size = 0; size < HAY_MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
{intMaxFound = true; break;}
// add hay to stack
haystack[size] = straw;
}
if (intMaxFound)
{
// ... broken
}
else
{
// ... ended naturally
}
The problem with this code is that the if statement is buried inside the loop body, and it takes some effort to locate it and understand what it does. A more clear (even without the break statement) variant will be:
bool intMaxFound = false;
for (size = 0; size < HAY_MAX && !intMaxFound; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
{intMaxFound = true; continue;}
// add hay to stack
haystack[size] = straw;
}
if (intMaxFound)
{
// ... broken
}
else
{
// ... ended naturally
}
In this case you can clearly see (just looking at the loop "header") that this loop can end prematurely. If the loop body is a multi-page text, written by somebody else, then you'd thank its author for saving your time.
UPDATE:
Thanks to SO - it has just suggested the already answered question about crash of the AT&T phone network in 1990. It's about a risky decision of C creators to use a single reserved word break to exit from both loops and switch.
Anyway this interpretation doesn't follow from the sample code in the original question, so I'm leaving my answer as it is.
You could possibly put the if into a foreach a for, a while or a switch like this
Then break and continue statements will be available
foreach ([1] as $i) if ($condition) { // Breakable if
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}
for ($i=0; $i < 1 ; $i++) if ($condition) {
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}
switch(0){ case 0: if($condition){
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}}
while(!$a&&$a=1) if ($condition) {
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}

Adding "else" at the end of an if-else statement [duplicate]

Our organization has a required coding rule (without any explanation) that:
if … else if constructs should be terminated with an else clause
Example 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Example 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
What edge case is this designed to handle?
What also concerns me about the reason is that Example 1 does not need an else but Example 2 does. If the reason is re-usability and extensibility, I think else should be used in both cases.
As mentioned in another answer, this is from the MISRA-C coding guidelines. The purpose is defensive programming, a concept which is often used in mission-critical programming.
That is, every if - else if must end with an else, and every switch must end with a default.
There are two reasons for this:
Self-documenting code. If you write an else but leave it empty it means: "I have definitely considered the scenario when neither if nor else if are true".
Not writing an else there means: "either I considered the scenario where neither if nor else if are true, or I completely forgot to consider it and there's potentially a fat bug right here in my code".
Stop runaway code. In mission-critical software, you need to write robust programs that account even for the highly unlikely. So you could see code like
if (mybool == TRUE)
{
}
else if (mybool == FALSE)
{
}
else
{
// handle error
}
This code will be completely alien to PC programmers and computer scientists, but it makes perfect sense in mission-critical software, because it catches the case where the "mybool" has gone corrupt, for whatever reason.
Historically, you would fear corruption of the RAM memory because of EMI/noise. This is not much of an issue today. Far more likely, memory corruption occurs because of bugs elsewhere in the code: pointers to wrong locations, array-out-of-bounds bugs, stack overflow, runaway code etc.
So most of the time, code like this comes back to slap yourself in the face when you have written bugs during the implementation stage. Meaning it could also be used as a debug technique: the program you are writing tells you when you have written bugs.
EDIT
Regarding why else is not needed after every single if:
An if-else or if-else if-else completely covers all possible values that a variable can have. But a plain if statement is not necessarily there to cover all possible values, it has a much broader usage. Most often you just wish to check a certain condition and if it is not met, then do nothing. Then it is simply not meaningful to write defensive programming to cover the else case.
Plus it would clutter up the code completely if you wrote an empty else after each and every if.
MISRA-C:2012 15.7 gives no rationale why else is not needed, it just states:
Note: a final else statement is not required for a simple if
statement.
Your company followed MISRA coding guidance. There are a few versions of these guidelines that contain this rule, but from MISRA-C:2004†:
Rule 14.10 (required): All if … else if constructs shall be terminated
with an else clause.
This rule applies whenever an if statement is followed by one or more
else if statements; the final else if shall be followed by an else
statement. In the case of a simple if statement then the else
statement need not be included. The requirement for a final else
statement is defensive programming. The else statement shall either
take appropriate action or contain a suitable comment as to why no
action is taken. This is consistent with the requirement to have a
final default clause in a switch statement. For example this code
is a simple if statement:
if ( x < 0 )
{
log_error(3);
x = 0;
} /* else not needed */
whereas the following code demonstrates an if, else if construct
if ( x < 0 )
{
log_error(3);
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
In MISRA-C:2012, which supersedes the 2004 version and is the current recommendation for new projects, the same rule exists but is numbered 15.7.
Example 1:
in a single if statement programmer may need to check n number of conditions and performs single operation.
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
In a regular usage performing a operation is not needed all the time when if is used.
Example 2:
Here programmer checks n number of conditions and performing multiple operations. In regular usage if..else if is like switch you may need to perform a operation like default. So usage else is needed as per misra standard
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
else if(condition_1 || condition_2 || ... condition_n)
{
//operation_2
}
....
else
{
//default cause
}
† Current and past versions of these publications are available for purchase via the MISRA webstore (via).
This is the equivalent of requiring a default case in every switch.
This extra else will Decrease code coverage of your program.
In my experience with porting linux kernel , or android code to different platform many time we do something wrong and in logcat we see some error like
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
printk(" \n [function or module name]: this should never happen \n");
/* It is always good to mention function/module name with the
logs. If you end up with "this should never happen" message
and the same message is used in many places in the software
it will be hard to track/debug.
*/
}
Only a brief explanation, since I did this all about 5 years ago.
There is (with most languages) no syntactic requirement to include "null" else statement (and unnecessary {..}), and in "simple little programs" there is no need. But real programmers don't write "simple little programs", and, just as importantly, they don't write programs that will be used once and then discarded.
When one write an if/else:
if(something)
doSomething;
else
doSomethingElse;
it all seems simple and one hardly sees even the point of adding {..}.
But some day, a few months from now, some other programmer (you would never make such a mistake!) will need to "enhance" the program and will add a statement.
if(something)
doSomething;
else
doSomethingIForgot;
doSomethingElse;
Suddenly doSomethingElse kinda forgets that it's supposed to be in the else leg.
So you're a good little programmer and you always use {..}. But you write:
if(something) {
if(anotherThing) {
doSomething;
}
}
All's well and good until that new kid makes a midnight modification:
if(something) {
if(!notMyThing) {
if(anotherThing) {
doSomething;
}
else {
dontDoAnything; // Because it's not my thing.
}}
}
Yes, it's improperly formatted, but so is half the code in the project, and the "auto formatter" gets bollixed up by all the #ifdef statements. And, of course, the real code is far more complicated than this toy example.
Unfortunately (or not), I've been out of this sort of thing for a few years now, so I don't have a fresh "real" example in mind -- the above is (obviously) contrived and a bit hokey.
This, is done to make the code more readable, for later references and to make it clear, to a later reviewer, that the remaining cases handled by the last else, are do nothing cases, so that they are not overlooked somehow at first sight.
This is a good programming practice, which makes code reusable and extend-able.
I would like to add to – and partly contradict – the previous answers. While it is certainly common to use if-else if in a switch-like manner that should cover the full range of thinkable values for an expression, it is by no means guaranteed that any range of possible conditions is fully covered. The same can be said about the switch construct itself, hence the requirement to use a default clause, which catches all remaining values and can, if not otherwise required anyway, be used as an assertion safeguard.
The question itself features a good counter-example: The second condition does not relate to x at all (which is the reason why I often prefer the more flexible if-based variant over the switch-based variant). From the example it is obvious that if condition A is met, x should be set to a certain value. Should A not be met, then condition B is tested. If it is met, then x should receive another value. If neither A nor B are met, then x should remain unchanged.
Here we can see that an empty else branch should be used to comment on the programmer's intention for the reader.
On the other hand, I cannot see why there must be an else clause especially for the latest and innermost if statement. In C, there is no such thing as an 'else if'. There is only if and else. Instead, the construct should formally be indented this way (and I should have put the opening curly braces on their own lines, but I don't like that):
if (A) {
// do something
}
else {
if (B) {
// do something else (no pun intended)
}
else {
// don't do anything here
}
}
Should any standard happen to require curly braces around every branch, then it would contradict itself if it mentioned "if ... else if constructs" at the same time.
Anyone can imagine the ugliness of deeply nested if else trees, see here on a side note. Now imagine that this construct can be arbitrarily extended anywhere. Then asking for an else clause in the end, but not anywhere else, becomes absurd.
if (A) {
if (B) {
// do something
}
// you could to something here
}
else {
// or here
if (B) { // or C?
// do something else (no pun intended)
}
else {
// don't do anything here, if you don't want to
}
// what if I wanted to do something here? I need brackets for that.
}
In the end, it comes down for them to defining precisely what is meant with an "if ... else if construct"
The basic reason is probably code coverage and the implicit else: how will the code behave if the condition is not true? For genuine testing, you need some way to see that you have tested with the condition false. If every test case you have goes through the if clause, your code could have problems in the real world because of a condition that you did not test.
However, some conditions may properly be like Example 1, like on a tax return: "If the result is less than 0, enter 0." You still need to have a test where the condition is false.
Logically any test implies two branches. What do you do if it is true, and what do you do if it is false.
For those cases where either branch has no functionality, it is reasonable to add a comment about why it doesn't need to have functionality.
This may be of benefit for the next maintenance programmer to come along. They should not have to search too far to decide if the code is correct. You can kind of Prehunt the Elephant.
Personally, it helps me as it forces me to look at the else case, and evaluate it. It may be an impossible condition, in which case i may throw an exception as the contract is violated. It may be benign, in which case a comment may be enough.
Your mileage may vary.
Most the time when you just have a single if statement, it's probably one of reasons such as:
Function guard checks
Initialization option
Optional processing branch
Example
void print (char * text)
{
if (text == null) return; // guard check
printf(text);
}
But when you do if .. else if, it's probably one of reasons such as:
Dynamic switch-case
Processing fork
Handling a processing parameter
And in case your if .. else if covers all possibilities, in that case your last if (...) is not needed, you can just remove it, because at that point the only possible values are the ones covered by that condition.
Example
int absolute_value (int n)
{
if (n == 0)
{
return 0;
}
else if (n > 0)
{
return n;
}
else /* if (n < 0) */ // redundant check
{
return (n * (-1));
}
}
And in most of these reasons, it's possible something doesn't fit into any of the categories in your if .. else if, thus the need to handle them in a final else clause, handling can be done through business-level procedure, user notification, internal error mechanism, ..etc.
Example
#DEFINE SQRT_TWO 1.41421356237309504880
#DEFINE SQRT_THREE 1.73205080756887729352
#DEFINE SQRT_FIVE 2.23606797749978969641
double square_root (int n)
{
if (n > 5) return sqrt((double)n);
else if (n == 5) return SQRT_FIVE;
else if (n == 4) return 2.0;
else if (n == 3) return SQRT_THREE;
else if (n == 2) return SQRT_TWO;
else if (n == 1) return 1.0;
else if (n == 0) return 0.0;
else return sqrt(-1); // error handling
}
This final else clause is quite similar to few other things in languages such as Java and C++, such as:
default case in a switch statement
catch(...) that comes after all specific catch blocks
finally in a try-catch clause
Our software was not mission critical, yet we also decided to use this rule because of defensive programming.
We added a throw exception to the theoretically unreachable code (switch + if-else). And it saved us many times as the software failed fast e.g. when a new type has been added and we forgot to change one-or-two if-else or switch. As a bonus it made super easy to find the issue.
Well, my example involves undefined behavior, but sometimes some people try to be fancy and fails hard, take a look:
int a = 0;
bool b = true;
uint8_t* bPtr = (uint8_t*)&b;
*bPtr = 0xCC;
if(b == true)
{
a += 3;
}
else if(b == false)
{
a += 5;
}
else
{
exit(3);
}
You probably would never expect to have bool which is not true nor false, however it may happen. Personally I believe this is problem caused by person who decides to do something fancy, but additional else statement can prevent any further issues.
I'm currently working with PHP. Creating a registration form and a login form. I am just purely using if and else. No else if or anything that is unnecessary.
If user clicks submits button -> it goes to the next if statement... if username is less than than 'X' amount of characters then alert. If successful then check password length and so on.
No need for extra code such as an else if that could dismiss reliability for server load time to check all the extra code.
As this question on boolean if/else if was closed as a duplicate. As well, there are many bad answers here as it relates to safety-critical.
For a boolean, there are only two cases. In the boolean instance, following the MISRA recommendation blindly maybe bad. The code,
if ( x == FALSE ) {
// Normal action
} else if (x == TRUE ) {
// Fail safe
}
Should just be refactored to,
if ( x == FALSE ) {
// Normal action
} else {
// Fail safe
}
Adding another else increases cyclometric complexity and makes it far harder to test all branches. Some code maybe 'safety related'; Ie, not a direct control function that can cause an unsafe event. In this code, it is often better to have full testability without instrumentation.
For truly safety functional code, it might make sense to separate the cases to detect a fault in this code and have it reported. Although I think logging 'x' on the failure would handle both. For the other cases, it will make the system harder to test and could result in lower availability depending on what the second 'error handling' action is (see other answers where exit() is called).
For non-booleans, there may be ranges that are nonsensical. Ie, they maybe some analog variable going to a DAC. In these cases, the if(x > 2) a; else if(x < -2) b; else c; makes sense for cases where deadband should not have been sent, etc. However, these type of cases do not exist for a boolean.

Equivalent using for-loop instead do-while-loop

I was wondering instead of using a do-while loop, what is the equivalent for-loop or any other combination of loops in c?
Any sort of a loop can be constructed from a combination of an infinite "forever" loop, and a conditional break statement.
For example, to convert
do {
<action>
} while (<condition>);
to a for loop, you can do this:
for (;;) {
<action>
if (!<condition>) break;
}
You can use the same trick to convert a do/while loop to a while loop, like this:
while (true) {
<action>
if (!<condition>) break;
}
Moreover, the loop is not needed at all: any of the above can be modeled with a label at the top and a goto at the bottom; that is a common way of doing loops in assembly languages. The only reason the three looping constructs were introduced into the language in the first place was to make the language more expressive: the do/while loop conducts author's idea much better than any of the alternatives shown above.
There is no other loop that executes the loop content at least once, as do-while does. Of course you could emulate do-while with a flag and a while loop:
do {
A;
} while (B)
becomes
int flag=1;
while (flag || B) {
flag=0;
A;
}
but that's not really an alternative, it just obscures your original intent.
The following three loops are all equivalent:
#define FALSE (0)
#define TRUE (!(FALSE))
do
{
status = getStatus();
}
while(status == TRUE);
status = TRUE;
while(status == TRUE)
{
status = getStatus();
}
for(status = TRUE; status == TRUE; status = getStatus())
{
}

What does for(;;) mean?

I am confused by the for(;;) construct. I think it is a form of shorthand for an unlimited for loop but I can't be sure.
Here is the code:
for(;;)
{
//whatever statements
}
Your guess is correct; it's an infinite loop.* This is a common C idiom, although many people (including me) believe the following to be less cryptic:
while (1) { whatever statements; }
* It's infinite assuming there are no break/return/etc. statements inside the loop body.
It's an un-terminated loop. It is sometimes written with a while:
while (1)
or even better:
while (true)
I would expect to see a break or return inside any such loop, no matter whether it is written with for or while. There has to be some abnormal control flow or it really will be an infinite loop.
Yes, that's the for C syntax with blank fields for initialization expression, loop condition and increment expression.
The for statement can also use more than one value, like this sample :
for (i=0, j=100, k=1000; j < 500 || i<50 || k==5000; i++, j+=2, k*=6) {};
Maybe one step beyond in for understanding ? =)
Yes, the expressions in the for loop are just optional. if you omit them, you will get an infinite loop. The way to get out is break or exit or so.
This statement is basically equal to:
while(1) {}
There is no start, no condition and no step statement.
As I understand it, for(;;) creates a deliberate non-exiting loop. Your code is expected to exit the loop based on one or more conditions. It was once provided to me as a purer way to have a do while false loop, which was not considered good syntax. Based on the exit condition, it is easier to dispatch to a function to handle the result, failure, warning, or success, for example.
My explanation may not be the reason someone used that construct, but I'll explain in greater detail what it means to me. This construct may be someone's "Pure C" way of having a loop in which you can serially perform multiple steps, whose completion mean something like your application has performed all steps of initialization.
#define GEN_FAILURE -99
#define SUCCESS 0
/* perform_init_step1() and perform_init_step2() are dummy
place-holder functions that provide a complete example.
You could at least have one of them return non-zero
for testing. */
int perform_init_step1();
int perform_init_step2();
int perform_init_step1()
{
return 0;
}
int perform_init_step2()
{
return 0;
}
int ret_code = GEN_FAILURE;
for(;;)
{
if(SUCCESS != perform_init_step1())
{
ret_code = -1;
break;
}
if(SUCCESS != perform_init_step2())
{
ret_code = -2;
break;
}
break;
}
If part of the initialization fails, the loop bails out with a specific error code.
I arrived at using C having done a lot of firmware work, writing in assembly language. Good assembly language programmers taught me to have a single entry point and single exit. I took their advice to heart, because their creed helped them and me immensely when debugging.
Personally, I never liked the for(;;) construct, because you can have an infinite loop if you forget to break; out at the end.
Someone I worked with came up with do..until(FALSE), but the amount of proper C furvor this caused was not to be believed.
#define GEN_FAILURE -99
#define SUCCESS 0
/* perform_init_step1() and perform_init_step2() are dummy
place-holder functions that provide a complete example.
You could at least have one of them return non-zero
for testing. */
int perform_init_step1();
int perform_init_step2();
int perform_init_step1()
{
return 0;
}
int perform_init_step2()
{
return 0;
}
int ret_code = GEN_FAILURE;
do
{
if(SUCCESS != perform_init_step1())
{
ret_code = -1;
break;
}
if(SUCCESS != perform_init_step2())
{
ret_code = -2;
break;
}
}
until (FALSE);
This runs once, no matter what.

Useful alternative control structures?

Sometimes when I am programming, I find that some particular control structure would be very useful to me, but is not directly available in my programming language. I think my most common desire is something like a "split while" (I have no idea what to actually call this):
{
foo();
} split_while( condition ) {
bar();
}
The semantics of this code would be that foo() is always run, and then the condition is checked. If true, then bar() is run and we go back to the first block (thus running foo() again, etc). Thanks to a comment by reddit user zxqdms, I have learned that Donald E. Knuth writes about this structure in his paper "Structured programming with go to statements" (see page 279).
What alternative control structures do you think are a useful way of organizing computation?
My goal here is to give myself and others new ways of thinking about structuring code, in order to improve chunking and reasoning.
Note: I'm not asking about how to generalize all possible control structures, whether by using jne, if/goto, Lisp macros, continuations, monads, combinators, quarks, or whatever else. I'm asking what specializations are useful in describing code.
One that's fairly common is the infinite loop. I'd like to write it like this:
forever {
// ...
}
Sometimes, I need to have a foreach loop with an index. It could be written like this:
foreach (index i) (var item in list) {
// ...
}
(I'm not particularly fond of this syntax, but you get the idea)
Most languages have built-in functions to cover the common cases, but "fencepost" loops are always a chore: loops where you want to do something on each iteration and also do something else between iterations. For example, joining strings with a separator:
string result = "";
for (int i = 0; i < items.Count; i++) {
result += items[i];
if (i < items.Count - 1) result += ", "; // This is gross.
// What if I can't access items by index?
// I have off-by-one errors *every* time I do this.
}
I know folds can cover this case, but sometimes you want something imperative. It would be cool if you could do:
string result = "";
foreach (var item in items) {
result += item;
} between {
result += ", ";
}
Loop with else:
while (condition) {
// ...
}
else {
// the else runs if the loop didn't run
}
{
foo();
} split_while( condition ) {
bar();
}
You can accomplish that pretty easily using a regular while:
while (true) {
foo();
if (!condition) break;
bar();
}
I do that pretty frequently now that I got over my irrational distaste for break.
If you look at Haskell, although there is special syntax for various control structures, control flow is often captured by types. The most common kind of such control types are Monads, Arrows and applicative functors. So if you want a special type of control flow, it's usually some kind of higher-order function and either you can write it yourself or find one in Haskells package database (Hackage) wich is quite big.
Such functions are usually in the Control namespace where you can find modules for parallel execution to errorhandling. Many of the control structures usually found in procedural languages have a function counterpart in Control.Monad, among these are loops and if statements. If-else is a keyworded expression in haskell, if without an else doesn't make sense in an expression, but perfect sense in a monad, so the if statements without an else is captured by the functions when and unless.
Another common case is doing list operation in a more general context. Functional languages are quite fond of fold, and the Specialized versions like map and filter. If you have a monad then there is a natural extension of fold to it. This is called foldM, and therefor there are also extensions of any specialized version of fold you can think of, like mapM and filterM.
This is just a general idea and syntax:
if (cond)
//do something
else (cond)
//do something
also (cond)
//do something
else
//do something
end
ALSO condition is always evaluated. ELSE works as usual.
It works for case too. Probably it is a good way to eliminate break statement:
case (exp)
also (const)
//do something
else (const)
//do something
also (const)
//do something
else
//do something
end
can be read as:
switch (exp)
case (const)
//do something
case (const)
//do something
break
case (const)
//do something
default
//do something
end
I don't know if this is useful or simple to read but it's an example.
With (lisp-style) macros, tail-calls, and continuations all of this is quaint.
With macros, if the standard control flow constructs are not sufficient for a given application, the programmer can write their own (and so much more). It would only require a simple macro to implement the constructs you gave as an example.
With tail-calls, one can factor out complex control flow patters (such as implementing a state machine) into functions.
Continuations are a powerful control flow primitive (try/catch are a restricted version of them). Combined with tail-calls and macros, complex control flow patterns (backtracking, parsing, etc.) become straight-forward. In addition, they are useful in web programming as with them you can invert the inversion of control; you can have a function that asks the user for some input, do some processing, asks the user for more input, etc.
To paraphrase the Scheme standard, instead of piling more features onto your language, you should seek to remove the limitations that make the other features appear necessary.
if not:
unless (condition) {
// ...
}
while not:
until (condition) {
// ...
}
Labeled loops are something I find myself missing sometimes from mainstream languages. e.g.,
int i, j;
for outer ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
if ( l1[ i ] == l2[ j ] )
break outer;
Yes, I can usually simulate this with a goto, but an equivalent for continue would require you to move the increment to the end of loop body after the label, hurting the readability. You can also do this by setting a flag in the inner loop and checking it at each iteration of the outer loop, but it always looks clumsy.
(Bonus: I'd sometimes like to have a redo to go along with continue and break. It would return to the start of the loop without evaluating the increment.)
I propose the "then" operator. It returns the left operand on the first iteration and the right operand on all other iterations:
var result = "";
foreach (var item in items) {
result += "" then ", ";
result += item;
}
in the first iteration it adds "" to the result in all others it adds ", ", so you get a string that contains each item separated by commas.
if (cond)
//do something
else (cond)
//do something
else (cond)
//do something
first
//do something
then
//do something
else (cond)
//do something
else
//do something
end
FIRST and THEN blocks runs if any of 3 conditionals are evaluated to true. FIRST block runs before the conditional block and THEN runs after the conditional block has ran.
ELSE conditional or final write following FIRST and THEN statement are independent from these blocks.
It can read as :
if (cond)
first()
//do something
then()
else (cond)
first()
//do something
then()
else (cond)
first()
//do something
then()
else (cond)
//do something
else
//do something
end
function first()
//do something
return
function then()
//do something
return
These functions are just a form to read. They wouldn't create scope. It's more like a gosub/return from Basic.
Usefulness and readability as matter of discussion.
How about
alternate {
statement 1,
statement 2,
[statement 3,...]
}
for cycling through the available statements on each successive pass.
Edit: trivial examples
table_row_color = alternate(RED, GREEN, BLUE);
player_color = alternate(color_list); // cycles through list items
alternate(
led_on(),
led_off()
);
Edit 2: In the third example above the syntax is maybe a bit confusing as it looks like a function. In fact, only one statement is evaluated on each pass, not both. A better syntax might be something like
alternate {
led_on();
}
then {
led_off();
}
Or something to that effect. However I do like the idea that the result of which ever is called can be used if desired (as in the color examples).
D's scope guards are a useful control structure that isn't seen very often.
I think I should mention CityScript (the scripting language of CityDesk) which has some really fancy looping constructs.
From the help file:
{$ forEach n var in (condition) sort-order $}
... text which appears for each item ....
{$ between $}
.. text which appears between each two items ....
{$ odd $}
.. text which appears for every other item, including the first ....
{$ even $}
.. text which appears for every other item, starting with the second ....
{$ else $}
.. text which appears if there are no items matching condition ....
{$ before $}
..text which appears before the loop, only if there are items matching condition
{$ after $}
..text which appears after the loop, only of there are items matching condition
{$ next $}
Also note that many control structures get a new meaning in monadic context, depending on the particular monad - look at mapM, filterM, whileM, sequence etc. in Haskell.
ignoring - To ignore exceptions occuring in a certain block of code.
try {
foo()
} catch {
case ex: SomeException => /* ignore */
case ex: SomeOtherException => /* ignore */
}
With an ignoring control construct, you could write it more concisely and more readably as:
ignoring(classOf[SomeException], classOf[SomeOtherException]) {
foo()
}
[ Scala provides this (and many other Exception handling control constructs) in its standard library, in util.control package. ]
I'd like to see a keyword for grouping output. Instead of this:
int lastValue = 0;
foreach (var val in dataSource)
{
if (lastValue != val.CustomerID)
{
WriteFooter(lastValue);
WriteHeader(val);
lastValue = val.CustomerID;
}
WriteRow(val);
}
if (lastValue != 0)
{
WriteFooter(lastValue);
}
how about something like this:
foreach(var val in dataSource)
groupon(val.CustomerID)
{
startgroup
{
WriteHeader(val);
}
endgroup
{
WriteFooter(val)
}
}
each
{
WriteRow(val);
}
If you have a decent platform, controls, and/or reporting formatting you won't need to write this code. But it's amazing how often I find myself doing this. The most annoying part is the footer after the last iteration - it's hard to do this in a real life example without duplicating code.
Something that replaces
bool found = false;
for (int i = 0; i < N; i++) {
if (hasProperty(A[i])) {
found = true;
DoSomething(A[i]);
break;
}
}
if (!found) {
...
}
like
for (int i = 0; i < N; i++) {
if (hasProperty(A[i])) {
DoSomething(A[i]);
break;
}
} ifnotinterrupted {
...
}
I always feel that there must be a better way than introducing a flag just to execute something after the last (regular) execution of the loop body. One could check !(i < N), but i is out of scope after the loop.
This is a bit of a joke, but you can get the behavior you want like this:
#include <iostream>
#include <cstdlib>
int main (int argc, char *argv[])
{
int N = std::strtol(argv[1], 0, 10); // Danger!
int state = 0;
switch (state%2) // Similar to Duff's device.
{
do {
case 1: std::cout << (2*state) << " B" << std::endl;
case 0: std::cout << (2*state+1) << " A" << std::endl; ++state;
} while (state <= N);
default: break;
}
return 0;
}
p.s. formatting this was a bit difficult and I'm definitely not happy with it; however, emacs does even worse. Anyone care to try vim?
Generators, in Python, are genuinely novel if you've mostly worked with non-functional languages. More generally: continuations, co-routines, lazy lists.
This probably doesn't count, but in Python, I was upset there was no do loop.
Anto ensure I get no upvotes for this answer, I wind up annoyed at any language I work in for any period of time that lacks goto's.
for int i := 0 [down]to UpperBound() [step 2]
Missing in every C-derived language.
Please consider before you vote or write a comment:
This is not redundant to for (int i = 0; i <= UpperBound(); i++), it has different semantics:
UpperBound() is evaluated only once
The case UpperBound() == MAX_INT does not produce an infinite loop
This is similar to the response by #Paul Keister.
(mumble, mumble) years ago, the application I was working on had lots of variations of so-called control-break processing -- all that logic that goes into breaking sorted rows of data into groups and subgroups with headers and footers. As the application was written in LISP, we had captured the common idioms in a macro called WITH-CONTROL-BREAKS. If I were to transpose that syntax into the ever-popular squiggly form, it might look something like this:
withControlBreaks (x, y, z : readSortedRecords()) {
first (x) : { emitHeader(x); subcount = 0; }
first (x, y) : { emitSubheader(x, y); zTotal = 0; }
all (x, y, z) : { emitDetail(x, y, z); ztotal += z; }
last (x, y) : { emitSubfooter(x, y, zTotal); ++subCount; }
last (x) : { emitFooter(x, subcount); }
}
In this modern era, with widespread SQL, XQuery, LINQ and so on, this need does not seem to arise as much as it used to. But from time to time, I wish that I had that control structure at hand.
foo();
while(condition)
{
bar();
foo();
}
How about PL/I style "for" loop ranges? The VB equivalent would be:
' Counts 1, 2, ... 49, 50, 23, 999, 998, ..., 991, 990
For I = 1 to 50, 23, 999 to 990 Step -1
The most common usage I can see would be to have a loop run for a list of indices, and then throw in one more. BTW, a For-Each usage could also be handy:
' Bar1, Bar2, Bar3 are an IEnum(Wazoo); Boz is a Wazoo
For Each Foo as Wazoo in Bar1, Bar2, Enumerable.One(Boz), Bar3
This would run the loop on all items in Bar1, all items in Bar2, Boz, and Bar3. Linq would probably allow this without too much difficulty, but intrinsic language support might be a little more efficient.
One of the control structures that isn't available in many languages is the case-in type structure. Similar to a switch type structure, it allows you to have a neatly formatted list of possible options, but matches the first one that's true (rather then the first one that matches the input). A LISP of such such (which does have it):
(cond
((evenp a) a) ;if a is even return a
((> a 7) (/ a 2)) ;else if a is bigger than 7 return a/2
((< a 5) (- a 1)) ;else if a is smaller than 5 return a-1
(t 17)) ;else return 17
Or, for those that would prefer a more C-like format
cond
(a % 2 == 0):
a; break;
(a > 7):
a / 2; break;
(a < 5):
a - 1; break;
default:
17; break;
It's basically a more accurate representation of the if/elseif/elseif/else construct than a switch is, and it can come in extremely handing in expressing that logic in a clean, readable way.
How about iterating with a moving window (of n elements instead of 1) through a list?
This is tangentially related #munificent's answer, I think.
Something like
#python
#sum of adjacent elements
for x,y in pairs(list):
print x + y
def pairs(l):
i=0
while i < len(l)-1:
yield (l[i],l[i+1])
i+=1
It is useful for certain types of things. Don't get me wrong, this is easy to implement as a function, but I think a lot of people try to bring out for and while loops when there are more specific/descriptive tools for the job.

Resources