Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84 exptools; site whuxl.UUCP Path: utzoo!watmath!clyde!cbosgd!ihnp4!mhuxn!mhuxr!mhuxt!houxm!whuxl!mike From: mike@whuxl.UUCP (BALDWIN) Newsgroups: net.lang.c Subject: Re: break, continue, return, goto Message-ID: <806@whuxl.UUCP> Date: Wed, 13-Nov-85 01:49:48 EST Article-I.D.: whuxl.806 Posted: Wed Nov 13 01:49:48 1985 Date-Received: Thu, 14-Nov-85 20:39:01 EST References: <771@whuxl.UUCP> <9500029@iuvax.UUCP> Organization: AT&T Bell Laboratories, Whippany Lines: 147 > Craig made good suggestions for not using "continue" and "break" > especially for the examples of Michael. "Continue" goto the beginning > of the loop. Replacing it with "else" would make the logic flow of the > codes following the "break" more smoothly. > > "Break" is generally interpreted as an exception where logic flow > is disrupted. But not disrupted in the sense of a goto; it is stricter. > But for the searching problem, both found and not found > are normal results. We can hardly interpret "not found" as an undesired > result. I said: I use *continue* and *returns* for errors, and *break* for search loops -- I never said that using break in that context was meant to indicate an error. > In general exception, like error in system call, will lead to > program abnormal termination. Error recovery is hard to achieve, because > logic flow is disrupted. You're exactly right. That's why continue and return are so nice. They give a reasonably clean way of dealing with these kinds of logic disruptions. > Too many times, programmers are seduced by > the use of break for a quick solution without spending time to structure > their program more. That is the same lesson we learned from advocating > goto-less programs. Oh, baloney! I happen to think that my use of continue/return/break in my code is perfectly well thought out and structured. If you think it's not just *BECAUSE* it uses continue/return/break, you're being too hasty. BREAK, RETURN AND CONTINUE ARE NOT THE SAME AS GOTO, FOLKS. IF THEY WERE, THEY'D ALL BE CALLED "GOTO". > In addition, I recommend the use of for loop be restricted to > its original meaning in natural language, i.e. as a loop with simple > counter. *Sigh*, not this again. The generalized for loop is one of the better things about C. WHY do you want this silly restriction? IF a for loop is being used with a simple counter, it will have one of a few forms, e.g., for (i = 0; i < MAX; i++). If YOU don't like funny for loops, then only use that form. And if you or I see that generic form, we KNOW that it's a simple for loop. So what's the big problem? If you don't have the general for loop, you say expr1; while (expr2) { stmt; expr3; } And now expr1, 2, and 3 are all split up. There are cases where they logically belong together but don't fit into the simple counter loop model, and this is exactly what the for loop is for! > With more complicate exit conditions, while loop fits better : > > m = meeble; > while ((m < meeble+NMEEBLE) && (m->glop==forp || m->zip==fweep)){ > /* walk thru the array till we hit the end or > * find the right one */ > ++m; > }; > if (m < meeble + NMEEBLE) { > /* found it */ > printf("zeegle %2s", m->yorg); > m->blazzo += IGUAP; > } else { > /* not found it */ > } > Sorry, I don't buy it. Here's the original code, that to me just plain looks simpler and better: for (m = meeble; m < meeble + NMEEBLE; m++) if (m->glop == forp || m->zip == fweep) { printf("zeegle %2s", m->yorg); m->blazzo += IGUAP; break; } In *THIS* version, the for loop is immediately recognizable as a simple for loop, and all the looping business with m is in one place. This really looks like another stupid religious style issue; which one of the two versions is in an absolute sense "better" cannot be determined. I prefer the latter, but the former is also acceptable to me. But you go so far as to say that the mere *USE* of break implies quick, hasty, poor design choices. That's going too far. > In some language like Pascal there is no conditional boolean operator, > we have to use boolean flages. With the availability of && and || in C, > exit conditions can be coded more explicitly than with boolean flags. Conditional and/or is another one of the great things C has. This is an aside, but most arguments against break/etc are that it isn't all pretty and provable. Well, && and || are much more of a pain to prove right in code than Pascal-ish and/or, and assignments in expressions wreak havoc. But I'm trying to write a program, not a thesis. In one of my courses, we used a very nifty language that was well-suited to logical proofs. The if stmt was like a lisp cond, and the easiest, cleanest way to describe it was that it picked one of the true clauses *at random*. None of this annoying ordering (as in && and ||) and no "else". It really is a very elegant and beautiful language and you can write proofs for programs easily, but *it's not supposed to be a real language* (I mean, how would you implement a non-deterministic if?). But a *real* language needs else, &&, ||, break, etc. Can anyone suggest a recoding of the following example without using multiple returns? Of course it can be done, but in a clearer, simpler way? Remember, this is exactly the same as using loops with continue. core(file) char *file; { if ((fd = open(file, O_RDONLY)) < 0) { perror(file); return; } if ((n = read(fd, &u, sizeof u)) == 0) { puts("zero length"); return; } if (n < sizeof u) { puts("too small"); return; } if (BADMAG(u.u_exdata.ux_magic)) { puts("not a core dump"); return; } /* process core dump */ printf("%d/%d %s", u.u_uid, u.u_gid, ctime(&u.u_start)); printf("$ %s\n", u.u_comm); /* ... etcetera */ } -- Michael Baldwin {at&t}!whuxl!mike