I know textbooks like to say goto statements are the devil, and I'm not fond of them at all myself, but does this justify an exception to the rule?

I'm looking for answers that deal with n-nested for loops.

NOTE: Whether you answer yes, no, or somewhere in between, completely close-minded answers are not welcome. Especially if the answer is no, then provide a good, legitimate reason why (which is not too far from Stack Exchange regulations anyway).

If you can write the inner loop condition as for (j = 10; j > 0 && !broken; j--) then you wouldn't need the break; statement. If you move the declaration of broken to before the outer loop begins, then if that could be written as for (i = 0; i < 10 && !broken; i++) then I think nobreak;s are necessary.
–
FrustratedWithFormsDesignerFeb 6 '14 at 21:59

8

Given the example is from C# - the C# reference on goto: goto (C# Reference) - "The goto statement is also useful to get out of deeply nested loops."
–
MichaelTFeb 6 '14 at 22:27

OMG, I never knew c# had a goto statement! The things you learn on StackExchange. (I can't remember the last time I wished for a goto statement capability, it doesn't seem to ever come up).
–
John WuFeb 6 '14 at 23:40

6

IMHO it really depends on your "programming religion" and current moonphase. For me (and most people around me) its fine to use a goto to get out of deep nests if the loop is rather small, and the alternative would be a superfluous check of a bool variable introduced just to have the loop condition break. This more so when you want to break out halfway through the body, or when after the innermost loop there is some code that would need to check the bool too.
–
PlasmaHHFeb 7 '14 at 10:29

1

@JohnWu goto is actually required in a C# switch to fall-through to another case after executing any code inside the first case. That is the only case I have used goto, though.
–
Dan LyonsFeb 7 '14 at 18:17

See my comments on the other answers. The original code prints i at the end of the outer loop, so short-circuiting the increment is important to making the code look 100% equivalent. I'm not saying anything in your answer is wrong, I just wanted to point out that breaking the loop immediately was an important aspect of the code.
–
p.s.w.gFeb 7 '14 at 0:36

1

@p.s.w.g I don't see any code printing i at the end of the outer loop in OP's question.
–
user61852Feb 7 '14 at 0:43

OP referenced the code from my question here, but left out that part. I didn't downvote you, BTW. The answer is entirely correct in regard to correctly choosing loop conditions.
–
p.s.w.gFeb 7 '14 at 0:47

2

@p.s.w.g I guess if you really really really really want to justify a goto, you can device a problem that needs one, on the other hand, I've been programming professionally for two decades and haven't a single real world problem that needs one.
–
user61852Feb 7 '14 at 0:52

1

The purpose of the code was not provide a valid use case for goto (I'm sure there are better ones), even if it spawned a question which seems to use it as such, but to illustrate the basic action of break(n) in languages which didn't support it.
–
p.s.w.gFeb 7 '14 at 0:58

Which is to say that yes, what you show is a needlessly complex way to break from nested loops, but no, there is a way to refactor that doesn't make a goto more appealing.
–
RogerFeb 6 '14 at 22:12

2

Just a side note: in the original code it prints i after the end of the outer loop. So to really reflect that i is the important value, here the return true; and return false; should both be return i;.
–
p.s.w.gFeb 6 '14 at 23:15

+1, was just about to post this answer, and believe this should be the accepted answer. I can't believe the accepted answer got accepted because that method only works for a specific subset of nested loop algorithms, and doesn't necessarily make the code much cleaner. The method in this answer works generally.
–
Ben LeeFeb 23 '14 at 2:18

Why do you even use broken in your first example at all? Just use break on the inner loop. Also, if you absolutely must use broken, why declare it outside the loops? Just declare it inside the i loop. As for the while loop, please don't use that. I honestly think it manages to be even less readable than the goto version.
–
luiscubalFeb 6 '14 at 22:30

@luiscubal: A variable named broken is used because I don't like using the break statement (except in switch-case, but that's about it). It's declared outside the outer loop in case you want to break ALL loops when i==j. You're right, in general, broken only needs to be declared before the outermost loop that it will break.
–
FrustratedWithFormsDesignerFeb 6 '14 at 22:37

In your update, i==2 at the end of the loop. The success condition should also short-circuit the increment if it is to be 100% equivalent to a break 2.
–
p.s.w.gFeb 6 '14 at 22:54

2

I personally prefer broken = (j == i) rather than the if and, if the language allows it, putting the broken declaration inside the outer loop initialisation. Though it's hard to say these things for this specific example, as the entire loop is a no-op (it returns nothing and has no side effects) and if it does something, it possibly does that inside the if (though I still like broken = (j ==i); if broken { something(); } better personally)
–
MartijnFeb 6 '14 at 22:55

@Martijn In my original code it prints i after the end of the outer loop. In other words the only really important think is when exactly it breaks out of the outer loop.
–
p.s.w.gFeb 6 '14 at 23:10

The short answer is "it depends". I advocate to choose regarding legibility and understandability of your code. The goto way might be more legible than tweaking the condition, or vice versa. You might also take into account least surprise principle, guideline used in the shop/project and consistency of the code base. For instance, goto to leave switch or for error handling is a common practice in the Linux kernel code base. Also note that some programmers might have problems reading your code (either raised with the "goto is evil" mantra, or just not learned because their teacher think so) and a few of them might even "judge you".

Generally speaking, a goto going further in the same function is often acceptable, especially if the jump is not too long. Your use case of leaving a nested loop is one of the known example of "not so evil" goto.

In your case, goto is enough of an improvement that it looks tempting, but it's not so much of an improvement that it's worth breaking the rule against using them in your code base.

Think of your future reviewer: s/he will have to think, "Is this person a bad coder or is this in fact a case where the goto was worth it? Let me take 5 minutes to decide this for myself or research it on the internet." Why on earth would you do that to your future coder when you can not use goto entirely?

In general this mentality applies to all "bad" code and even defines it: if it works now, and is good in this case, but creates effort to verify it's correct, which in this era a goto will always do, then don't do it.

That being said, yes, you produced one of the slightly thornier cases. You may:

use more complex control structures, like a boolean flag, to break out of both loops

put your inside loop inside its own routine (likely ideal)

put both loops in a routine and return instead of breaking

It's very hard for me to create a case where a double-loop isn't so cohesive that it shouldn't be its own routine anyway.

By the way, the best discussion of this I've seen is Steve McConnell's Code Complete. If you enjoy thinking of these problems critically I strongly recommend reading, even cover-to-cover despite its immensity.

It's our job programmers to read and understand code. Not just simplistic code unless that is the nature of your codebase. There are, and will always be exceptions to the generality (not rule) against using gotos because of the understood cost. Whenever the benefit outweighs the cost is when goto should be used; as is the case for all coding decisions in software engineering.
–
dietbuddhaFeb 7 '14 at 9:41

1

@dietbuddha there is cost in violating accepted software coding conventions that should be adequately taken into account. There is cost in increasing the diversity of control structures used in a program even if this control structure may be a good fit for a situation. There is cost in breaking static analysis of code. If this is all still worth it then who am I to argue.
–
djechlinFeb 7 '14 at 13:02

For the specific example you used I would say no for the same reasons many other have pointed out. You can easily refactor the code into an equivalently good form which eliminates the need for the goto.

In general the proscription against goto is a generality based on the understood nature of goto and the cost of using it. Part of software engineering is making implementation decisions. Justification of those decisions occurs by weighing the cost against the benefits and whenever the benefits outweigh the cost the implementation is justified. Controversy arises because of different valuations, both of cost and benefit.

The point is there will always be exceptions where a goto is justified, but only for some because of different valuations. The pity is many engineers simply exclude techniques in purposeful ignorance because they read it on the internet rather than taking the time to understand why.