Xref: utzoo misc.misc:6228 comp.misc:6151 Path: utzoo!attcan!uunet!twwells!bill From: bill@twwells.uucp (T. William Wells) Newsgroups: misc.misc,comp.misc Subject: Re: The "evil" GOTO (Was: 25 Years of BASIC) Message-ID: <933@twwells.uucp> Date: 18 May 89 20:28:21 GMT References: <1791@ubu.warwick.UUCP> <1436@onion.reading.ac.uk> <1814@ubu.warwick.UUCP> <1860@ubu.warwick.UUCP> <2491@koto.cs.vu.nl> <77467@ti-csl.csc.ti.com> Reply-To: bill@twwells.UUCP (T. William Wells) Organization: None, Ft. Lauderdale Lines: 150 Summary: Expires: Sender: Followup-To: Distribution: Keywords: In article <77467@ti-csl.csc.ti.com> gateley@m2.UUCP (John Gateley) writes: : I haven't seen anybody mention what I consider to be the most valid : use of goto: implementing new control structures. For languages without : coroutines, a sufficiently powerful goto can be used to implement them. : This is true for any new control structure. It does seem that the memory of the net gets shorter all the time. I reposted the enclosed article less than two weeks ago, and the GOTO flamers are *still* acting if the words were never said. (For those whose memory isn't that short, yes I've updated the article a little.) === Under ordinary circumstances, there is exactly one place where a human C coder might use a goto. This is to implement multi-level breaks and continues. I say this, having managed (and written huge chunks of) a 17,000 line software system (and that is only the part we sell, and does not include development tools). I've developed several other software systems, each involving many thousands of lines of C code. I have programmed in C for seven years now and have NEVER used a goto. We have uncounted megabytes of C code written in-house. None of it contains a goto. With that aside, let me explain why the goto discussion is really fruitless. People have observed that gotos are used in a lot of bad code. From this it is concluded that gotos are bad. This is really bad logic. Try this: programmers have been observed to write bad code; therefore, programmers are bad! THERE IS NOTHING WRONG WITH GOTO. (And how do I reconcile with my mouthing off above? Wait and see...) The thing that is screwed up is the control structures being implemented with the gotos. One whole point of the structured programming debate is this: every program has a control structure; some of these control structures are better than others. Whether you use gotos or some other language feature to implement the control structure does not change what the control structure is nor does it affect the goodness of the control structure. The quality of your program is strongly influenced by the quality of its control structures. Furthermore, you want that control structure to be obvious and understandable to the reader of the program. This implies that you use language features that make your use of a control structure obvious. So, the first question should be: what are the good control structures? The second question should be: given a particular language, how should the control structures be implemented? Ok, so what makes a control structure good? Well, the basic answers are: a control structure is good if it is 1) appropriate to solving programming problems. 2) easy to write. 3) easy to understand. 4) easy to maintain. 5) ... add your own as long as they do not contradict the above There are obviously lots of control structures that meet these requirements and you do not have to use all of them. In fact, you should pick a set of those which are most appropriate for your programming environment and use them. This set should be, in some sense, a minimum one; for example, if you have two control structures which can accomplish the same thing, but one is easier to use than the other (for you), pick the easier one and forget the other. All other things being equal, a smaller number of control structures helps make your program easier to understand. Now, I hope my claim about our C programs is understandable. But if not, here is what it amounts to: I have chosen a set of control structures which is appropriate to programming in C, for the kind of programming tasks that I do. It happens that, while my set of control structures includes multi-level breaks and continues (which could be implemented with a goto), I have never had need to implement one with a goto. Given the amount of code I write, it seems to me that one might never need to use an explicit goto in C code. There is a reason to avoid naked gotos in your code: for all other keywords, the control structure being implemented is obvious. But for goto it isn't. You can make the control structure obvious by clothing the goto in some preprocessor magic. As an example, suppose that you are using the state machine control structure. I normally code it as: state = STATE_INIT; while (state != STATE_DONE) { switch (state) { case STATE_INIT: ... } } However, this is not the most efficient way to do it. You could also implement it as: /* Wherever you see these macros being used, you will be seeing a state machine. The state macro defines the start of a state. The enter_state macro causes a transfer of control to another state of the same machine. The leave macro sends you to the end of the machine, the end_machine macro marks the place where the machine ends. */ #ifndef SDEBUG #define state(m, label) m##label:; #define end_machine(m) m##_finish:; #else #define state(m, label) printf("warning: falling though\n"); \ m##label: printf("entering state " #label \ " of machine " #m "\n"); #define end_machine(m) m##_finish:printf("leaving machine " #m "\n"); #endif #define enter_state(m, label) goto m##label #define leave(m) goto m##_finish state(input_interp, INIT) ... code for the INIT state enter_state(input_interp, MORE); state(input_interp, MORE) ... code for the MORE state if (nomore) { leave(input_interp); } else if (error) { enter_state(input_interp, RECOVER); } enter_state(input_interp, MORE); state(input_interp, RECOVER) ... code for the RECOVER state enter_state(input_interp, FUDGE_INPUT); ... end_machine(input_interp) Some of you will no doubt be thinking: but why should I go to all this effort when I could just use the goto directly? Well, if this was all you did with goto, I don't really see any reason why not (but I do think your program should include a comment saying that you use goto for state machines and describes how you structure it). If, however, you have more than one way of using goto, you should clothe the gotos somehow so that the reader of the program knows what control structure your goto belongs to. --- Bill { uunet | novavax } !twwells!bill