It's certainly fair enough to say that the advantage may not be "great", but nonetheless I think it could be nice to have. And, I'll show you a reasonable example of it, after replying to some of the other statements.
Quote
In all seriousness, though: when adding features to a language you reach a point of diminishing returns. The more stuff a language has in it, the more difficult it is to learn, and the greater the chance of unintended consequences. C++ has arguably already reached that point and gone far beyond it! So a feature like this that doesn't seem like it would be useful that often, and would provide at best a marginal benefit in the use cases it does encounter, just doesn't make the bar.
It's hardly even like "adding a new feature", it's more like completing the general control pattern of dependent control so that it applies to all relevant structures rather than just if.
Quote
By the way, if I've understood your proposal correctly, you don't actually need 'else while' to be a construct. You only need the 'else' clause on while loops; then 'else while' falls out naturally from C++ syntax rules, just like 'else if' does from chained ifs.
By that logic, then you could also say that you "don't really need else-if either" because it also follows from if and else. Thus, by your logic, you analogously argue that we should write dependent if statements as follows:
if(condition 1) {
//actions
}
else {
if(condition 2) {
//actions
}
else {
if(condition 3) {
//actions
}
else {
if(condition 4) {
//actions
}
else {
//actions
}
}
}
}
:wacko:
But this is unwieldy, hence it is better to write it with else-ifs.
Writing the conditions in "else while" multiple times goes against the general programming principle that identical equivalent things should only have to be modified once (i.e. through 1 "variable").
Quote
I think those constructs are not natural (apart from their nearly non-existant real world use, as Reedbeta pointed out already).
If I read "if", than the "else" does tell me what to do otherwise. Consider "while(X) else Y"; I read something like "as long as X, but otherwise Y", or "do X until Y, otherwise Z".
This is neither natural, nor logical to me.
Regardless of how it reads to you, that's not how a dependent control structure works. Else clauses create a dependent control structure, and the definition of a dependent control structure is that only one clause in it will execute. That's the whole point of dependent control structures, and it's why else clauses are different from unconditional code following a conditional.
Also, programs precede sequentially through code and don't go backward unless you explicitly tell them to. Interpreting it as switching between the various conditions and actions, rather than exiting from whichever dependent control statement was selected, is contrary to the sequential nature of dependent control structures.
Quote
Sidenote: This reminds me of a performance optimization:
My use of a do while for the "else while" was indeed a performance optimization. It probably would have been clearer if I had wrote it in the slightly more wasteful, but more clean form. Apologies.
Quote
I'd love the original poster to post a case where this is useful.. of course it's possible that in some programming styles you might end up writing things that way. Still, an example might illuminate things somewhat.
:happy:
I'd gladly give you an example. Here's an example of using it in an internal list iterator. It may not be as efficient as an external iterator (do to redundancy), but it at least illustrates the use of the control construct. Consider it as pseudo-code.
//current_index declared somewhere in List class
Node List::operator[](int target_index) {
distance = target_index - current_index;
while(distance > 0) {
go_to_next_node();
--distance;
}
else while(distance < 0) {
go_to_prev_node();
++distance;
}
return current_node;
}
Having to perform a particular distinct looping sequence of operations based on a condition (such as when on one side of a boundary or on the other side) is a
very common phenomenon and can be more succinctly written with "else while" control. Sure, it's so simple for binary conditions that one may not really care to have it available, but for more complex algorithms that involve more than two cases it could be a nice shorthand, especially if there's additional levels of nesting involved in subsections of the algorithm.
Otherwise (without "else while") you would write as follows:
//current_index declared somewhere in List class
Node List::operator[](int target_index) {
distance = target_index - current_index;
if(distance > 0) {
while(distance > 0) {
go_to_next_node();
--distance;
}
}
else if(distance < 0) {
while(distance < 0) {
go_to_prev_node();
++distance;
}
}
return current_node;
}
Which, as I've said, forces you to write two identical conditions for each loop (which is bad).
Note however, that the function would in this case be more efficiently coded as follows (rather than either of the above two):
Node List::operator[](int target_index) {
distance = target_index - current_index;
if(distance > 0) {
while(distance--) { go_to_next_node(); }
}
else if(distance < 0) {
while(distance++) { go_to_prev_node(); }
}
return current_node;
}
( Or, you could alternatively put "return current_node" statements after each while loop. Putting it at the end though, makes it so you only have to maintain one of such return statements (i.e. constant order), rather than one for each (i.e. linear order). )
Nonetheless, it doesn't change the fact that the example that used the "else while" construct remedied the obnoxious issue of maintaining two separate copies of the condition. The fact that the more optimal form in this case had a while loop inside an if isn't necessarily going to be the case for other uses of the "else while". We were able to do that simply because of the dual use of the count integer as a condition check, which won't always be possible for other constructs.
One other (less important) way it could of been programed is like this:
Node List::operator[](int target_index) {
distance = target_index - current_index;
while(distance != 0) {
if(distance > 0) {
go_to_next_node();
--distance;
}
else if(distance < 0) {
go_to_prev_node();
++distance;
}
}
return current_node;
}
But, such a construct could make the program check things it already knows multiple times. Once we know the target index is on one side or the other, we don't need to check the other side. So, this form is also inferior to the "else while" for this particular purpose.
As for macros, I generally try to avoid them as much as possible. The quirks and name collisions are unpleasant and harder to debug. Better to protect whoever ends up maintaining the code from them as much as possible.
Quote
A do else wouldn't make sense, because the condition is only evaluated after the first iteration, and for a switch else you have the default case label.
That's true I suppose. I hadn't yet fully consider those ones, and had included them in the post for the sake of completion (i.e. so that the discussion would include them).
Apologies.
On a different subject though, it should be noted that I'm not talking about a single while loop that executes different things depending on conditions. What I'm talking about is a dependent control structure made up of while loops (and/or other things), which is different.
I am aware of the continue statement.
Is this what you meant, SamuraiCrow?:
while(condition) {
if(condition 1) {
//actions to perform
continue;
}
else if(condition 2) {
//actions to perform
continue;
}
else {
//actions to perform
}
}
If so, you don't need the continue statements anyway, unless there was more code in the while loop (or other loop type) that you needed to avoid executing. The dependent control structure would jump to the end of the while loop any time one of the clauses executed, and from there would continue to the top again on its own accord anyway.
Again, if this is what you meant, you should know it's not what I'm talking about. It doesn't even do the same thing as my example did. Strictly speaking, your example wouldn't even compile. Continue statements are only valid in loops and your "equivalent" example wasn't in one.
Perhaps you could explain what you meant, SamuraiCrow. I'm not sure if I understand your point.
My example only executes either the first while loop, the second while loop, or the else block. It never executes more than one particular block. It might execute one particular block
multiple times, but it never executes multiple blocks in the dependent control structure. This is my intent.
Anyway, I guess I'll leave it at that for now.
Thanks for reading and responding. Sorry for the length of my reply. Hopefully I wasn't too wordy. :lol: