tischler@ihuxs.UUCP (Mark D. Tischler) (10/02/84)
A while ago, someone told me that they thought it was possible to break out of several nested loops at once using a statement like "break 3". It would, for example, break out of the following sequence: i = 1; while . . for . . switch . . break; i = 2; It doesn't seem to work, and I was wondering if perhaps someone knew of a way to do that without having to set 3 separate boolean flags? Please send mail to me. Thanks. -- Mark Tischler (312) 420-7272 (home) (312) 979-2626 (work) ihnp4!ihuxs!tischler
td@alice.UUCP (Tom Duff) (10/03/84)
The correct way to break out of multiply nested control constructs (using the example in the referenced article) without using 3 separate boolean flags is: i=1; while(...){ ... for(...;...;...){ ... switch(...){ ... goto Out; } } } Out: i=2;
buls@ssc-vax.UUCP (Rick Buls) (10/04/84)
>> The correct way to break out of multiply nested control constructs (using the >> example in the referenced article) without using 3 separate boolean flags is: >> >> i=1; >> while(...){ >> ... >> for(...;...;...){ >> ... >> switch(...){ >> ... >> goto Out; >> } >> } >> } >> Out: i=2; >> >> Very UNstructured!!!!!!!!!! Try the following: i=1; struct(????); i=2; ... struct(????) ... { ... while(...){ ... for(...;...;...){ ... switch(...){ ... return; } } } } where ???? is what ever parameters are needed!!!!
dan@digi-g.UUCP (Dan Messinger) (10/04/84)
If possible, you could make that section of code a seperate function, and use 'return' from any point in the nested loops to effectively break out. The number of parameters that would be needed to be passed to this routine could make this unacceptable, in which case you could use the dreaded 'goto'.
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/06/84)
Hurray for Tom Duff, too! It's amazing how programmers resort to great contortions to avoid a simple, clean forward goto to break out of nested loops.
hansen@pegasus.UUCP (10/08/84)
One of the proposals that was supposed to be brought up before the last committee meeting was a way to make breaking out of deeply nested loops structured such that the following: >> i=1; >> while(...){ >> ... >> for(...;...;...){ >> ... >> switch(...){ >> ... >> goto Out; >> } >> } >> } >> Out: i=2; >> would become: >> i=1; -- whileloop: >> while(...){ >> ... >> for(...;...;...){ >> ... >> switch(...){ >> ... -- break whileloop; >> } >> } >> } >> i=2; >> The idea is to be able to label while, for and do-while loops and be able to use those labels on break and continue statements. This provides for a very structured and much more readable and maintainable coding style, in my opinion, than the equivalent code using goto's or separate procedures. This feature is commonly called a "break n" capability in the literature and other languages. What does everyone think? Is this a worthy attempt at making the language more structured and orthogonal? Send in your votes! Tony Hansen pegasus!hansen
padpowell@wateng.UUCP (PAD Powell) (10/09/84)
I love the idea of labelled loops. Just make sure that you support "break <label>;" and "continue <label>". Just to make life really simple, PROHIBIT multiple labels with the same name in a procedure body. Should cause no problems, should make LINT a joy to use, as you would not get "warning: label redefinition..." messages. Patrick Powell
ignatz@wlcrjs.UUCP (David M. Ihnat) (10/09/84)
<I'll never submit to putting in that silly lineater sop in my messaes...>
(Despite the fact that the latest version of news encourages me to
reship the entire text of the reference message, I can't see doing so.
If you're stepping into this conversation this late, uh...go back and
catch up.)
Re the comment on the suggestion to use a 'goto' to get out of deeply
nested structures:
> Very UNstructured!!!!!!!!!!
Sorry--STRUCTURED CODE IS NOT RELIGION. If trying for structured code
produces more complicated, un-understandable code than the so-called
'unstructured' code, then it's getting in the way of the job. Please,
please remember: Nothing is forbidden. Gotos CAN be avoided in all
cases; but it remains a fact that there are times when a simple,
single exit point out of a deeply nested structure will be far clearer
and simpler than a convoluted approach intended to appease the ghods
of structured programming. (FYI, I *am* a proponent of structured
programming techniques; the approach I'm postulating, fortunately, was
explained to me by aprofessor long gone but not forgotten.)
Dave Ihnat
Analysts International Corporation
ihnp4!wlcrjs!ignatz
ihnp4!aicchi!ignatz
ihnp4!wlcrjs!aicchi!ignatz
--
Dave Ihnat
Analysts International Corporation
aicchi!ignatz or wlcrjs!ignatz
(w) 882-4673 (h) 784-4544
td@alice.UUCP (Tom Duff) (10/10/84)
It's hard to imagine how this proposal (break with a label argument breaks out of the labelled statement) could be considered `more structured' than a goto. It's nothing more than a goto that goes to the statement after the one with the label. Of course, the next thing you'll want is to do the same thing to continue. That could make continue the semantic equivalent of goto. The only restriction would be that you could only use these things from within the labelled statement. This is the sort of proposal that closet spaghetti-chefs pull out because they haven't got the talent or perverted mindset (or whatever it takes) to write their code without gotos. They hope that by changing the name and mumbling nonsense about reducible flow-graphs they can get the structured-programming fascists to give them back 99% of their gotos. Neither side of the goto argument should be satified with this sort of thing. Those in favor of gotos should not hide their lamp under a bushel, but should expose it to all of us, if not in pride then as fair warning. Those opposed should denounce the proposal as invidious subversion. To quote Ken Thompson: `if you want go get somewhere, GOTO is the way to do it.' If you're going to write code that jumps all over the place, have the grace not to whitewash it.
crm@duke.UUCP (Charlie Martin) (10/10/84)
I may be dense, but I simply cannot see what makes label: while ( cond ) { ... if ( break cond ) break label ; } any more structured'' than while( cond ) { ... if ( break cond ) goto end ; } end : ; In addition, the construct above has the advantage that it looks like it is doing what it is really doing -- that is, the break label'' version says that it is breaking a loop labellled label'', which label is at the beginning, but it is effectively GOING to the END. Don Knuth wrote an article that was pretty good on Structured Programming With GOTO's that covered all off this sort of thing, by the way -- I can dig up a formal reference if needed. Charlie Martin (...mcnc!duke!crm)
rogerh@arizona.UUCP (Roger Hayes) (10/10/84)
Tony Hansens' proposal was to allow labels on loops, like
foo: while (x)
{
...
.{.
break foo;
.}.
}
I like the idea of named loops. This syntax is very bad (sorry, Mr.
Hansen). Is foo a legal label? Can one say "goto foo"? Is this fragment
legal? (If so, what does it mean?)
baz: i += j;
break baz;
I am not pleased with any of the alternatives I have thought of for syntax.
The problem is to give a name to the loop body, without creating an ambiguity
with any other legal construct, and hopefully by using something that will
seem familiar to present C users. It would be nice to avoid making another
keyword.
I have thought of, and rejected:
while (x) foo: { ... } foo
while (x) loop foo { ... } foo
while (x) foo:: { ... } foo
I like the first best, but it does create two kinds of labels (on regular
statements and on compound statements) with the same syntax, but different
semantics. I put trailing labels (which must match the name of the loop)
on all of them, because I want a marker to see where the break will jump
to, without counting levels of braces.
Roger Hayes
University of Arizona
Dept. of Computer Science
PS: I am strongly in favor of more-than-6-character-names in the C standard.
In addition to all the reasons advanced so far, the C language is tied pretty
closly to UN*X, and UN*X is headed towards flexnames. Let the inconvenience
be on the past (6-chars) not on the future.
radford@calgary.UUCP (Radford Neal) (10/10/84)
I think labelling loops and allowing one to break out of several by using that label is NOT a good idea for the ANSI standard. What does this really get you? Nothing as far as I can see. Breaking out of nested loops with a goto is not at all obscure. The only advantage of a multi-level exit from a structured programming point of view is that it guarantees that only forward branches are made, presumably increasing readability. The proposal manages to avoid this advantage, however, by using the same syntax for a label used as the object of a goto as for a label used in a break. If I came across a label at the beginning of a while loop, my first impression would be that someone RESTARTS the loop by jumping there. If you really want to do such things, the best construct is the "situation case" proposed by C. T. Zahn. This works like this: notice-situation <situation1>, <situation2>, ... ... <code, including statements like "situation-occurs <situation>"> ... case <situation1>: <code> case <situation2>: <code> ... end (This isn't a proposal for a C-oriented syntax.) In the block of code at the beginning, statements can occur indicating that a particular situation has occured (possibly in deeply nested contexts). After this block are a number of (optional) sections of code that get jumped to when the corresponding situations arise. After that section of code is done, the statement following all this gets done. This gets you multi-level exits and more as well, in a potentially more understandable form. REALLY though, none of this is neccessary. I find that single level exits are quite convenient 95% of the time, and gotos work fine for the rest. I really thought this was all settled five years ago during the great structured programming debate. Using a goto statement once every few thousand lines of code is perfectly reasonable. Furthermore, this is just the sort of thing which should NOT go in a standard, as it would render all existing compiler non-standards-conforming for no good reason, reducing the probability that the standard will be taken seriously. Anybody who went out and wrote lots of code using the new construct thinking it was portable because it was "standard" would be fooling themselves. Radford Neal Dept. of Computer Science University of Calgary
jim@randvax.UUCP (Jim Gillogly) (10/11/84)
-------------- Breaking out of a nested loop with a "break label" instead of a GOTO is supposed to be much better for program verification. Rather than being an arbitrary control transfer, it merely exits from a well-defined environment. At least that's what Bill Wulf told us when he invented it for BLISS. The only time I use GOTO's in C is to get out of these loops, and I write a whole lot of C. I heartily concur with David Dyer-Bennett's assertion that "break label" is much better than "break n", having used and tried to debug with both in BLISS. I would add an outer loop now and then and forget that there was an "exitloop 3" on the next screen. For stand-alone completeness, we're talking about leaving nested loops as follows: label: for (i = 0; i < n; i++) { ... for (j = 0; j < m; j++) { ... if (error) break label; } } Jim Gillogly {vortex, decvax}!randvax!jim
quiroz@rochester.UUCP (Cesar Quiroz) (10/11/84)
> Tony Hansens' proposal was to allow labels on loops, like > foo: while (x) > { > ... > .{. > break foo; > .}. > } > > I like the idea of named loops. This syntax is very bad (sorry, Mr. > Hansen). Is foo a legal label? Can one say "goto foo"? Is this fragment > legal? (If so, what does it mean?) > > baz: i += j; > break baz; > I think the proposed syntax is not that bad. First of all, it doesn't introduce a new usage in C, labels are already valid where proposed. Now, the idea requires a simple extension to the semantics of the language, namely: That 'break <label>' works only for breakable statements! This, of course, means two things: 1._ That <label> refers to a 'breakable' statement, 2._ That the break occurs inside the range of that statement. You can add a field to the 'label' entries in your symbol table (say 'breakable'). You set this flag appropriately as soon as you recognize what type of statement your label is adorning. (Minor difficulties can arise if you allow <label> [<label> ..] <statement>, because you have to fix not just one label, but this shouldn't be a concern here). Then, if you see break foo; (as per the example) you can determine that the usage is valid. On the other hand, 'break baz;' is nonsense, can be easily shown to be that, and can be handled properly (it 'breaks' your whole program :-)). It should go without saying, but the compiler shouldn't scream "syntax error", because 'break <label>' would be a syntactically valid construction, but an error message like "cannot break from ..." or "unbreakable ..." (but not "stainless ..." :-)) Additional remarks concerning the competence of the perpetrator are usually considered unnecessary or in bad taste. There is also the (unrelated?) proposal of adding the same label at the end of a compound statement. Sound as it is, retrofitting it into a language seems too painful in terms of the expected benefits. Cesar Augusto Quiroz Gonzalez Department of Computer Science {allegra|seismo}!rochester!quiroz University of Rochester or Rochester, NY 14627 quiroz@ROCHESTER
dat@hpcnoe.UUCP (dat) (10/11/84)
I have to agree. One of the biggest problems in the realm of professional programmers (hows THAT for a concept!) (scary) is that they don't understand that there CAN BE EXCEPTIONS TO EVERY RULE. Sure it is good to try to avoid goto's like the plague, but in some cases it IS the best possible approach. My last job was with a DoD contractor and we had in writing that we COULD NOT USE ANY GOTO's. PERIOD. NO EXCEPTIONS. And we were using Fortran VII so there weren't a whole lot of alternatives in some cases. I just foisted the code that I felt necessitated the 'goto' to someone else and bypassed the whole issue) What the hell - Assembler and 'Spaghetti Code' are interesting, and a CHALLENGE to debug (especially if it ain't commented and it ain't yours!) right? We're getting too wimpy. :-) Structuredly, Dave Taylor Colorado Networks
rcd@opus.UUCP (Dick Dunn) (10/11/84)
> >> The correct way to break out of multiply nested control constructs (using the > >> example in the referenced article) without using 3 separate boolean flags is: >... > >> while(...){ >... > >> goto Out; > > Very UNstructured!!!!!!!!!! > > Try the following: ...and the parent article suggests ripping this nest out into a separate procedure which has, as parameters, all of the variables needed in the nest of control constructs--this allows replacing the "goto" with a "return". I guess the trailing-line-eater bug got the parent article, 'cause there wasn't a ":-)" at the end. I'm sure glad to see that someone would violate all concepts of modularity (yanking part of the innards out of a procedure), clean interface (defining a new procedure without regard to how many parameters might be needed), and, dare I say the word, efficiency. No, really, I AM glad about that, because the more "programmers" there are who bow to the sacred "structured" idol and who stupidly believe "structured"=="no goto's", the longer I will be able to be paid an absurdly high salary for being able to produce real software (though it's sometimes painful to do maintenance on code written by a "structured code" dogmatist). -- Dick Dunn {hao,ucbvax,allegra}!nbires!rcd (303)444-5710 x3086 ...Relax...don't worry...have a homebrew.
rcd@opus.UUCP (Dick Dunn) (10/11/84)
Bad confusion on the multi-level break issue: > One of the proposals that was supposed to be brought up before the last > committee meeting was a way to make breaking out of deeply nested loops > structured such that the following: > [illustration of multi-level-break problem] > would become: > -- whileloop: >... > -- break whileloop; >... > The idea is to be able to label while, for and do-while loops and be able to > use those labels on break and continue statements. This provides for a very > structured and much more readable and maintainable coding style, in my > opinion, than the equivalent code using goto's or separate procedures... >... > What does everyone think? Is this a worthy attempt at making the language > more structured and orthogonal? Send in your votes! The idea for such a language construct is reasonable, but it should not be muddled into the standardization process. Standards committees working on existing languages are NOT in the role of designing, or even revamping, a language. Naturally, they will have to make some changes--but only for those situations where there is a very real problem in the existing form(s) of the language. In fact, the proposed construct does not answer any particular crying need. Multi-level breaks are comparatively uncommon. They certainly aren't so common and so much of a problem as to justify a CHANGE to the language. Finally, the proposed solution has a very interesting characteristic: Without the extension, the multi-level break has two parts--a transfer and a label. With the extension, the multi-level break has two parts--a transfer and a label. The notable difference is that with the extension, the label is at a different point (possibly by quite a distance) than the point to which control is actually transferred. I'm hard-pressed to see that as an advantage. -- Dick Dunn {hao,ucbvax,allegra}!nbires!rcd (303)444-5710 x3086 ...Relax...don't worry...have a homebrew.
quiroz@rochester.UUCP (Cesar Quiroz) (10/12/84)
Minimal editing done in quotes below!_ <From a posting by Charlie Martin (...mcnc!duke!crm)> > I may be dense, but I simply cannot see what makes > ... > break label ; > > any more structured'' than > ... > goto end ; > ... > end : ; > I, for one, will not say that one of the constructs is more ''structured'' that the other. Nor I couldn't care less. For the 'structured'/'unstructured' debate usually moves real fast into religious beliefs. What makes me decide for the 'break' style over the 'goto' style is a set of other considerations. To start with, you may agree (so I hope) that the few goto's that are really harmless (or unavoidable) are the ones that take you out from a loop/procedure or some other flow of control commitment into safe code again. Like the one above, which is probably less dangerous than adding flags to check how to get out. (My typing errors increase exponentially with the number of declarations). However, if those are really the only goto's we really want, why bother implementing the whole power of an all purpose 'goto'? To take your own words on this matter: > In addition, the construct above has the advantage that it > looks like it is doing what it is really doing -- that is, the > break label'' version says that it is breaking a loop labellled > label'', which label is at the beginning, but it is effectively > GOING to the END. > Yes, 'break' (or 'exit' or whatever reason may suggest) says what it is doing. And it can do only what it says, no more no less. In addition, 'break' is NOT going to the end. It's going beyond :-) > Don Knuth wrote an article that was pretty good on Structured > Programming With GOTO's that covered all off this sort of > thing, by the way -- I can dig up a formal reference if needed. > Amen brother. Every side seems to have a Holy Book. (And yes, the article is really good -- my copy appears in Raymond Yeh's collection "Current Trends in Programming Methodology", Vol.1, Prentice Hall (1977), but there is a footnote that says that the copyright is by ACM (1974)). But again, best arguments don't use religion. Cesar Augusto Quiroz Gonzalez {allegra|seismo}!rochester!quiroz
ron@brl-tgr.ARPA (Ron Natalie <ron>) (10/12/84)
The major advantage of not introducing a new construct which is redundant to the old goto construct is that you'll still have to keep the goto around (it really is part of the language) and why complicate the language with yet another unstructured construct. -Ron
crm@duke.UUCP (Charlie Martin) (10/12/84)
The problem with getting into a religious discussion is that everyone seems to think that you have a religious opinion... Let me make another attempt to make my argument clear -- I claim that while it is indeed true that ANY algorithm can be expressed in proper structured-programming-without-goto's (proven by Boehm & Jacopini), there are things which one often wants to do which are best expressed in current programming languages (modulo efficiency constraints) by doing them with a goto. The example that we have been discussing is one of those. The solutions that are available are: use a branching statement to bust out of the loop; have a language construct which magically hides a branching contruct busting out of the loop; or put a new boolean test into each outer loop, so that processing terminates when that is set. The third solution is the one that can be inferred from the original proof. It has some advantages for proof-of-correctness. The second method is the one that is used by the break (and continue) statements, and is the one that I feel is correct. It limits the scope of the goto, and doesn't tempt people into indiscetions as often. However, these statements as they exist won't cover certain cases: for example, a simple break won't take you out of nested loops; a more difficult example is something like this: /* code for user input */ while ( not complete ) do retry: /* transfer to this point for retry of whole thing */ while( not right) do get input a, b, c if ABORT-INPUT received goto retry fi od od /* end example */. In both of these cases, WHILE IT IS PROVABLY POSSIBLE TO WRITE A GOTO-LESS PROGRAM TO DO THEM, the solution with goto's has advantages in speed and amount of generated code-and-data. The best solution is something that eliminates goto's or limits their ability to muck up control flow, but that provides for all those odd situations which these exemplify. A label-continue/label-break sentax might do that effectively (say by defining the label as an optional part of the beginning and/or ending of a loop) but I want to feel convinced that it is going to be able to do everything I would use a goto for (which isn't damnall much, I admit -- I've only written one goto in C ever.) (And wouldn't have ever written one in Pascal at all, were it not for the absense of a loop break.) My only complaints about the labelled-loop/break-label solution are these: 1) it's a goto anyway -- why fuss about it? In particular, why claim it is more ``structured'' than the same control- flow with the horrible word ``goto'' in the code? 2) The notation suggested is itself counter-intuitive -- you are G*T*-ing to a label, but the label is up at the top and you are going to the bottom (!?) 3) do these solutions *really* cover everything? Are you going to leave setjmp/longjmp in the language? They can be transformed out too, you know... Charlie Martin (...mcnc!duke!crm)
hansen@pegasus.UUCP (Tony L. Hansen) (10/13/84)
This following is a formal proposal for an addition to the ANSI Standard C language. This is a modification of an August draft of the standards document. Tony Hansen pegasus!hansen ---- Subject: labels Currently labels are allowed within the language only as targets of goto statements. I would like to propose that they be allowed in two additional places as well: as arguments to the break and continue statements. Consider the code fragment while (...) { weekloop: while (...) { ... switch (...) { ... case ...: ... goto endloop; ... goto endloop2; ... } ... endloop: ; } endloop2: ... } Where does the "goto endloop" logically take us? What it is actually doing is continuing the second while loop (labeled weekloop). Is it obvious from the code? I think that when looking at that code and seeing the goto, I would look for the label, possibly scanning the entire function for it. Finally I would find the label within the same loop as the switch statement. I would then see the closing brace following the label and search back for the matching opening brace. Finally I would see that it is a pair of braces from a while loop and going to that place will do the same thing as a continue of that loop. Similarly, where does the "goto endloop2" logically take us? What it is actually doing is breaking out of the second while loop. Is that obvious from the code? I feel that the same mental juggling around would have to be done to figure out what the real affect of the goto is. Instead, I would like to propose the following code fragment: while (...) { weekloop: while (...) { ... switch (...) { ... case ...: ... continue weekloop; ... break weekloop; ... } ... } ... } Here I have used the logically extended continue and break statements to accept a label argument. Think through the mental juggling that now has to be done to realize what happens when the continue statement is reached: "Hmmm, weekloop has to have been defined above. ... There it is. And it's being continued. That's simple enough to follow." Similarly for the new break statement. I can tell almost at a glance which loop is being continued or broken out of rather than doing all sorts of mental juggling to figure out what the goto is really doing. I propose that section 6.5 be rewritten along the following lines: 6.5 Jump statements The jump statements (goto, continue, break, and return) cause an unconditional jump to another place. 6.5.1 Labeled statements Syntax identifier : statement Constraints Any statement may be preceded by a label prefix that serves to declare the identifier as a label. The only use of a label is as a target of a goto, continue or break statement. The labels are in a separate name space from other identifiers. 6.5.2 goto statements Syntax goto identifier ; Semantics Control may jump unconditionally by means of the goto statement. The identifier must be a label located anywhere in the current function. 6.5.3 Syntax continue identifier ; opt Constraints A continue statement may appear only in a loop body. The optional identifier must be a label prefixing a while, for or do iteration statement enclosing the continue statement. Semantics A continue statement causes a jump to the loop-continuation portion of the enclosing iteration statement; that is, to the end of the loop. If no label is specified, the smallest enclosing iteration statement is used; otherwise the labeled enclosing iteration statement is used. More precisely, in each of the statements loop: loop: loop: while (...) { do { for (...) { ... ... ... continue; continue; continue; ... ... ... continue loop; continue loop; continue loop; ... ... ... contin: ; contin: ; contin: ; } } while (...); } unless the continue shown without a label reference is in an enclosed iteration statement (in which case it is interpreted within that statement), it is equivalent to "goto contin;". (Following the contin: is a null statement.) Irregardless of other enclosing iteration statements, the "continue loop" statement is equivalent to "goto contin;". 6.5.4 The break statement Syntax break identifier ; opt Constraints A break statement may appear only in a switch body or loop body. The optional identifier must be a label prefixing a switch statement, or a while, for or do iteration statement, enclosing the break statement. Semantics A break statement without a label identifier terminates execution of the smallest enclosing switch or iteration statement. A break statement with a label identifier terminates execution of the enclosing switch or iteration statement which is prefixed with the named identifier. More precisely, in each of the statements loop: loop: loop: while (...) { do { for (...) { ... ... ... break; break; break; ... ... ... break loop; break loop; break loop; ... ... ... } } while (...); } contin: contin: contin: ... ... ... unless the break shown without a label reference is in an enclosed switch or iteration statement (in which case it is interpreted within that statement), it is equivalent to "goto contin;". Irregardless of other enclosing switch or iteration statements, the "break loop" statement is equivalent to "goto contin;". 6.5.5 The return statement ....
geoff@desint.UUCP (Geoff Kuenning) (10/13/84)
I think some people in the pro-break camp are missing some of the pro-goto's point. Suppose you are reading this code: label1: for (i = 0; i < n; i++) { while (x ()) { ... if (condition) break label1; *or* goto label2; } } label2: Assume we have a fairly large program here; perhaps the outer loop won't actually fit on a 24-line screen (give me an Ann Arbor, please!). Now, when you come to the "break" statement, and you want to follow the code flow, what do you do? Obviously, you search (upwards) for label1. Then you have to fight Bell-style curly-brace conventions to locate the end of the loop, which is where the next statement executed will actually be found. What a pain! With the unrestricted goto, of course, you have no idea which direction to search in, so the problem is even worse. But if, like most modern programmers, the author used goto's *only* to break out of nested loops, you can count on a forward search. And when you find the matching label, you are done! The disadvantage of unrestricted goto's is not so much program validation as optimization (quick: you are compiling the statement at "label2". What's in the registers? What if there's a backwards jump in the code below?). This was the reason Dijkstra originally criticized goto's (and, by the way, he *did* explicitly state that completely goto-less programs were superior--the title of his 1968 letter to CACM was "Goto's Considered Harmful"). I think that we need a restricted form of the goto (like the break <label>), but in a syntax that places the target at the next statement executed. This would allow compiler writers to do good global optimizations. One solution might be to leave the language syntax alone, but add a compiler switch that says, in effect, that all goto's are of the restricted "break" form, and it can safely make this assumption when optimizing. Even better, we could make that be the default, and require the switch when compiling programs that had unrestricted goto's. The advantage of this is that we could call the switch "-bozo" :-). -- Geoff Kuenning First Systems Corporation ...!ihnp4!trwrb!desint!geoff
henry@utzoo.UUCP (Henry Spencer) (10/14/84)
> ... if those are really the only goto's we really want, why bother > implementing the whole power of an all purpose 'goto'? ... Because the all-purpose goto, revolting though it is, already exists in C and does not need re-inventing. Personally, I think "return" makes a dandy multi-level exit; I haven't used, or missed, goto for years. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
henry@utzoo.UUCP (Henry Spencer) (10/14/84)
> ...and the parent article suggests ripping this nest out into a separate > procedure which has, as parameters, all of the variables needed in the nest > of control constructs--this allows replacing the "goto" with a "return". > I guess the trailing-line-eater bug got the parent article, 'cause there > wasn't a ":-)" at the end. > > I'm sure glad to see that someone would violate all concepts of modularity > (yanking part of the innards out of a procedure), clean interface (defining > a new procedure without regard to how many parameters might be needed), > and, dare I say the word, efficiency. ... Gee, I've always found that modularity and clean interface were *improved* by breaking the innards out into a separate function any time they start getting non-trivial. As an accidental side effect of this, "return" then suffices for multi-level exits. And it's never produced any efficiency problems in my stuff. Efficiency is the standard excuse for ugliness, and that's usually all it is: an excuse. Note that I am not suggesting that you can retrofit this approach into existing code without rethinking said code to make it clean and modular. -- Henry Spencer @ U of Toronto Zoology {allegra,ihnp4,linus,decvax}!utzoo!henry
honey@down.FUN (10/14/84)
to make program verification easier, i hereby renounce the use of goto's forever. please send a program verifier to the above address. peter honeyman
jec@iuvax.UUCP (10/15/84)
[just in case] I don't think the labelling of loops is all that necessary for the "break"ing out of loops, but it would be nice to have it for the "continue"ing of loops. As long as it is being used for continuing why not allow it and keep goto for those that like to do it the other way. -- James Conley Indiana University 68K Education Board Project ...{isrnix|iuvax}!jec
bright@dataio.UUCP (Emperor) (10/15/84)
Since breaking out of several nested loops is unstructured anyway, isn't using an unstructured goto the most appropriate thing to do? I've seen some pretty unreadable 'structured' code caused by attempts to avoid using gotos, when a rewrite of the code using a goto simplified it tremendously. Walter Bright
gino@voder.UUCP (Gino Bloch) (10/15/84)
[this is a broken loop] Well, I have an opinion too. I imagine trying to find WHERE the break or goto takes me to. Assume that I have a listing or an editor without the `%' command. I think it's easier to guess what happens with this: while (...) { { { { ... goto bkpt; } } bkpt: ... } } than it will be with this: while (...) { someloop: while (...) { { { ... break someloop; } } } } Except, of course, in simple cases that aren't very deeply nested - but those cases are easy anyway. -- Gene E. Bloch (...!nsc!voder!gino)
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/16/84)
Gee, I thought everyone knew that the most general structured loop is startloop ... on condition (...) leaveloop ... repeatloop which can mimic a "while" or "do .. while" loop if one or the other of the body sections is null. The rules for "structuredness" seem to be: a loop invariant is being maintained (and is stated EXPLICITLY, perhaps in a comment), the loop is entered at the top, and there is only one exit from the loop. C's "break" and "continue" violate this just as much as a "goto" would. But so what; a conscientious program designer will "think structured" no matter what language he is using. I have yet to see an automated tool (including ADA) for enforcing proper programming practice that can compensate for ignorance or stupidity on the part of its user.
lwall@sdcrdcf.UUCP (Larry Wall) (10/16/84)
In article <468@voder.UUCP> gino@voder.UUCP (Gino Bloch) writes: >Well, I have an opinion too. I imagine trying to find WHERE the break or >goto takes me to... So do I, and so do I... Hypothetical examples of named breaks never ring quite true, because they neglect the fact that most loops have a semantic value. I think this point has been neglected by the pro-namers. Named loops (and blocks) are useful *abstractions*, and it's always nice to be able to name your abstractions. Arguments about whether your abstraction should be named at the beginning or the end miss the point. If a loop is to be labeled, it should be labeled at both ends. I can just see it: the Los Angeles City Council argueing about whether to post an "Entering Los Angeles" sign at the north end or the south end of I-5... _ Now, does that mean we should add named loops to C? me genoito! I don't think you should turn C into Ada*, for two reasons: 1) Those who think they don't like Ada will think they won't like C. (Yes, that's what I meant to say.) 2) Those who think they like Ada will already have switched to Ada. (Yes, yes, I know. Hope springs eternal...) For all her faults, Ada knows an abstraction when she sees one. C is easy, but a clever lady is worth waiting for. Larry Wall {allegra,burdvax,cbosgd,hplabs,ihnp4,sdcsvax}!sdcrdcf!lwall *Ada iartoUSDOD(AJPO).
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/17/84)
The "break looplabel;" and "continue looplabel;" proposals should not be added to the C language because they provide no additional functionality but complicate compilation. As has been repeatedly pointed out in this debate, they are not any clearer than similar use of "goto label;". Part of the spurious argument to the contrary assumes the silly K & R brace conventions are being used (sorry, guys, you're still my heroes). Tell me how while ( condition ) { ... if ( emergency ) goto forward; ... } forward: is any harder to comprehend than backward: while ( condition ) { ... if ( emergency ) break backward; ... } Unless the proposal is combined with outlawing "goto", nothing is gained by it. However, the ANSI committee better not outlaw "goto" since a large amount of existing C code, including a few UNIX system utilities, would be broken by this. Sure, one could rewrite code like again: ... if ( this_one_not_it ) goto again; ... to use some other looping mechanism, but the point is not to force the massive amount of rewriting that this would entail. Otherwise non-standard compilers are going to be maintained indefinitely anyway, which defeats the purpose of trying to outlaw "goto".
ron@brl-tgr.ARPA (Ron Natalie <ron>) (10/17/84)
> Gee, I thought everyone knew that the most general structured loop is > startloop > ... > on condition (...) leaveloop > ... > repeatloop Gee, finally someone brought up the world-famous do { ... } while { ... } loop. -Ron "DOD Committee to Stop ADA" Natalie
crm@duke.UUCP (Charlie Martin) (10/18/84)
While I thought the referenced article was pretty good all-in-all, the "managers, students, and other children" flame was low. I used to be a manager, I'm now a student, I'm *THOROUGHLY* conversant with the issues involved in Structured Programming (and what about the cognative psychology issues? We haven't covered those yet...) and I firmly believe that those people who have been proposing the labelled-loop idea have string and reasoned opinions for their obviously incorrect opinions. ( what is the net-glyph to indicate a sarcastic tone?) So cool it on the "children" bit, OK? Charlie Martin (...mcnc!duke!crm) === improv signature line === I am NOT a CHILD! I am a Software Engineer! === end sig ===
arnold@ucsfcgl.UUCP (Ken Arnold%UCB) (10/23/84)
> ... > > For stand-alone completeness, we're talking about leaving nested loops as > follows: > > label: > for (i = 0; i < n; i++) > { ... > for (j = 0; j < m; j++) > { ... > if (error) > break label; > } > } > > Jim Gillogly {vortex, decvax}!randvax!jim Under this proposal, what does the following code do: if (condition) goto label; ... label: for (i = 0; i < n; i++) { ... for (j = 0; j < m; j++) { ... if (error) break label; } } Does the "goto label" go to the top of the for loop, while the "break label" goes to the bottom? Or is this semantically incorrect code, which the compiler should complain about? What this shows is that we are really talking about two seperate things, both designated by "<identifier>:". In C currently, this is a marker in the code to name a place where control can be transfered. The proposed addition would use the same syntax to name a loop so that "break" and "continue" statements can make reference to it. These two meanings are not entirely compatible. So what does it mean to "goto" a block? Does it mean to go to the first executable statement inside the block? Does it mean to go to the controlling statement of the block (in the above example, to "for (i = ...)") if it has one. (Note that blocks can exist without controlling statments; are such blocks nameable, "break"- and "continue"-able?). And, even with such questions resolved in some fashion, how is the compiler to know whether "<identifier>:" is a label or a block name? I will say that I do not like the proposal (if you couldn't have guessed), but I would like to know precisely what it is I don't like :->. I have always wanted a nice way to get out of such nested loops, but I haven't seen one yet that is as clear as a goto with a good label name. And, I might warn those of you who find goto's inherently evil, that even were this accepted, there are still areas where (at least in C) a goto is the clearest way to code something, so "goto"s will still be used, even by style-conscious structure freaks like me. Ken Arnold
stanton@fortune.UUCP (W. Dean Stanton) (10/23/84)
> > Gee, I thought everyone knew that the most general structured loop is > > startloop ... on condition (...) leaveloop ... repeatloop > Gee, finally someone brought up the world-famous > do { ... } while { ... } loop. > -Ron "DOD Committee to Stop ADA" Natalie You probably wanted an expression after "while": do <statement> while (expression) <statement> and might have also thought of: do <statement> until (expression) <statement> An interesting generalization of if-then-else, while, and do-until (even more general than C's for :-) appears in CACM, Aug. 1983 (vol. 26, number 8), page 572: "A Generalized Control Structure and Its Formal Definition" by David Lorge Parnas. The idea was to define a structured "algorithm". The compiler (or whatever) can generate whatever gotos are necessary to implement it. My sample C syntax for the "it" (iterate) command follows. Read "it" as "iterated-if", "then" as my arrow-substitute, *done* as my substitute for a downward-arrow meaning all done with this "it" (don't iterate), and *loop* as my substitute for an upward-arrow meaning iterate back to the first test after "it", "elseif" was chosen to imply that you can string as many of these as you wish off of one "it", "else" (a la default) is always taken if you no earlier branch was taken. [I'm quoting, I can edit it]: -- read until "success" but at most numtry times count=1; read(raw_data, success); it (success) then true_data=FUNC(raw_data) *done* elseif (count < NUM_TRIES) then read(raw_data, &success); count++; *loop* else *done* ti; If you can't tell, when you it *loop*, you (dare I say it?) go-to the "it". When you it the *done*, you go-to the ti. If the redundant calls to read bother you, too, they fix it with a compile-time flag, "init" (meaning, "first time through the loop") and even "non init" ("any time except first"): -- read until "success" but at most numtry times -- COR is conditional || operator (does not evaluate rest unneccessarily count=0; it (init COR (not success) && count < NUM_TRIES) then read(raw_data, &success); count++; *loop* elseif (success) then true_data=FUNC(raw_data) *done* else *done* ti; The compiler handles the "init" by building an initial branch to the read. Later loops return to the (not success) test. Neat, huh? - W. Dean Stanton, Graphics Software UUCP: {decvax!ihnp4,ucbvax!amd,hpda,sri-unix,harpo}!fortune!stanton USPS: Fortune Systems Corp, 101 Twin Dolphin Drive, Redwood City, CA 94065 Phone: (415) 594-2835 "A standard can always be improved. But it won't be; this is why it is a standard." - A. Lesea & R. Zaks
chris@hwcs.UUCP (Chris Miller) (10/24/84)
In all the discussion on the merits and/or degree of structuredness of constructs such as "break <unsigned integer>" or "break <label>" I have not yet seen anyone observe that C ALREADY has a partial mechanism for getting out of several nested loops without using a GOTO - it is called "return"! Example (using current C - translate ad lib. to your favourite syntax, and make identifiers unique within 6 chars :-)): level_1: while (condition_1) { while (condition_2) { while (condition_3) { switch (condition_4) { case AGAIN: goto Cont; /* I.E. continue level_1 */ case FINISHED: goto Done; /* I.E. break level_1 */ default: ... } } } Cont: } Done: Becomes: level_1(/* Parameters from current environment */); ... level_1(/* Parameters */) { while (condition_1) if (level_2(/* Parameters */) == Done) return; } level_2(/* Parameters */) { while (condition_2) { while (condition_3) { switch(condition_4) { case AGAIN: return Cont; case FINISHED: return Done; default: ... } } } return Done; } If you want multi-level breaks/continues, it is even possible to return a count indicating how many levels of loop are to be exited. Let me defend myself instantly from rising hackles and cries of "Efficiency!". If you really have a collection of nested loops, then in most cases, the cost of starting up the outer ones is small compared with the cost of repeatedly executing the innermost one. It may therefore not be altogether unreasonable to parcel the whole lot up as a separate function; it is likely in most cases to be a great deal more readable that way, as well. Lest anyone still be inclined to flame, a few more points: 1. I am NOT saying that the above is "more" or "less" structured than any other proposal. Simply wrapping things in procedures does not automatically render them structured, modular, maintainable, readable, or anything else! 2. I AM pointing out that if you want to write unstructured code in C, you don't even need the existing "goto", "break", or "continue" statements - "return" is quite sufficient (let alone "longjmp", "exit", or, if you want to be truly obscene, "kill" to transfer control to a routine which has been set up for signal trapping :-)). 3. I am NOT seriously advocating the above translation as a general technique - often a solution with "goto" is perfectly appropriate and comprehensible. 4. I do not believe that "goto" should be banned from C (on the principle of not breaking existing software), and on the whole do not favour introducing unnecessary further constructs - if there had never been a "goto" in C to start with, things would be different, but there was so they aren't. 5. The REAL problem with any construct, structured or otherwise is that it becomes hard to read if applied to too large a physical scope (very large loop bodies, distant targets of "break", etc.). On C compilers which support multi-line macro definitions (i.e. V7 and most later ones) a considerable gain in clarity, at no cost in efficiency, can be gained by packaging loop bodies as macros, even if they only appear once in the code. 6. I am a computational atheist. -- Chris Miller Department of Computer Science Heriot-Watt University ...!ukc!{edcaad,west44}!hwcs
lambert@mcvax.UUCP (Lambert Meertens) (10/25/84)
: I propose the creation of a new newsgroup, "net.lang.c.nestedloopbreak". The last selector is a bit of a finger twister; better suggestions, anyone? A major advantage of this newsgroup would be that no-one (unless s/he desired so) would have to wade through all this stuff of marginal interest in net.lang.c to get to the really interesting discussion of how to get out of deeply nested loops. (How did we get in in the first place? :-) Another possibility is setting up "mod.lang.c.nestedloopbreak". I am willing--somewhat reluctantly, since fascism is not exactly fashionable--to serve as the moderator of such a group. -- Lambert Meertens ...!{seismo,philabs,decvax}!lambert@mcvax.UUCP CWI (Centre for Mathematics and Computer Science), Amsterdam
stuart@ncoast.UUCP (Stuart Freedman) (10/29/84)
> I propose the creation of a new newsgroup, "net.lang.c.nestedloopbreak". > The last selector is a bit of a finger twister; better suggestions, anyone? > A major advantage of this newsgroup would be that no-one (unless s/he > desired so) would have to wade through all this stuff of marginal > interest in net.lang.c to get to the really interesting discussion of > how to get out of deeply nested loops. (How did we get in in the first > place? :-) Why not just use rn? I think that this program has most of what we need in order to make a newsgroup serviceable to everyone by deleting things one doesn't want to see. Now just watch people start using creative subject lines, just so that we will have to see their postings!!! -- Stuart Freedman decvax!cwruecmp!ncoast!stuart Case Western Reserve University
smk@axiom.UUCP (Steven M. Kramer) (11/02/84)
Besides not using goto for structured reasons, I don't use it because many optimizers barf when it is used and the resulting code runs slower. -- --steve kramer {allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk (UUCP) linus!axiom!smk@mitre-bedford (MIL)
jim@ISM780B.UUCP (11/03/84)
>While I thought the referenced article was pretty good all-in-all, >the "managers, students, and other children" flame was low. It was "managers, students and other children, ..." (note the commas) which is quite different. If you aren't a child, or a manager who is technically uneducated, then this doesn't apply to you, so why get upset? My point was that there _a_r_e many people on the net who are very inexperienced and/or uneducated and they would do well to temper their opinion of their own opinions, and do some reading in the subject. I was not stating any opinion about the value of structured programming or of structured constructs per se (in fact I regard them highly); rather, I was talking about them in the context of the C standardization effort specifically, and in the context of sweeping generalizations made about stuctured programming by _s_o_m_e on the net. -- Jim Balter, INTERACTIVE Systems (ima!jim)
crm@duke.UUCP (Charlie Martin) (11/05/84)
Contrary to your note, there is no difference between "managers, students, and other children" and "managers, students and other children" -- they have the same meaning. Check for example Fowler's book on English Usage or a modern style manual, like that of the New York Times. In addition, I have been a manager and am now a student and I still feel pretty certain that I am included in the class to which you ascribed a childish lack of knowledge. -- Can you say "classical fallacy?" Good! I *knew* you could. Charlie Martin (...mcnc!duke!crm)