mirk@warwick.UUCP (Mike Taylor) (05/04/89)
In article <3, I think> gould@rosemary.cs.reading.ac.uk (Adrian Gould) writes: > Lets eradicate the GOTO from all languages. I hate it when people say things like that; As if you can just wave a magic wand over a language by excising GOTO, and everything will be alright. Listen, just 'cause Quiche-eater Wirth connected GOTOs with lack of structure geenrally, doesn't mean either that (A) ALL use of GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code is due to use of GOTO -- so why is it that so many people seem to believe these myths? How many times have you seen this kind of code? printf ("Enter your sex: "); while (sex != "m" && sex != "f") { gets (sex); if (sex != "m" && sex != "f") printf ("<m> or <f> only: "); } Why make the test twice? Huh? Huh? Answer me that, all you obsessed anti-GOTO campaigners. The *natural* way to express the above is: printf ("Enter your sex: "); LABEL: gets (sex); if (sex != "m" && sex != "f") { printf ("<m> or <f> only: "); GOTO LABEL; } Better examples abound, but in time honoured way, elude me now that I need them. How many times have you seen people using "for (;;;) ... break;" when you *know* that by "break" they mean "GOTO"? In many situations GOTO is natural - the response of a thinking being to it is to traid to know when those times are. Clearly irresponsible use of GOTO is bad; clearly spaghetti-junction programs written in languages with no other flow-control are bad (Frog knows how APL people manage!) But let's get this in perspective. It isn't GOTO's fault. It's yours for using it badly. It makes me laugh when people push Ada as a good real-time langauge because iof its "powerful exception-handling". "Exception-handling". Do you know what that means? Yup, you guessed it, it's a fancy word for GOTO. Luverly, Eh? Dress it up to look nice'n'respectable, install it as a fabulous feature in a DoD-sponsored langauge-to-end- all-languages, and everyone loves it. Well they ain't fooling me. I know goto when I see it. The reason Ada seems more powerful for having GOTO is simply because the programming paradigm that is pushed together with Ada causes the programmer to use GOTO in a disciplined way. THAT is the answer to the GOTO problem. Teach people to recognise WHEN to use it, and teach them to know HOW to use it. ______________________________________________________________________________ Mike Taylor - {Christ,M{athemat,us}ic}ian ... Email to: mirk@uk.ac.warwick.cs Unkle Mirk sez: "G G7/B C F G G7/B B7 Em; Dm7 G7/B C Gdim7 G D C Gdim7 G D Cm"
rang@cpsin3.cps.msu.edu (Anton Rang) (05/05/89)
In article <1814@ubu.warwick.UUCP> mirk@warwick.UUCP (Mike Taylor) writes: [ ... ] Listen, just 'cause Quiche-eater Wirth connected GOTOs with ^^^^^ lack of structure generally, doesn't mean either that (A) ALL use of GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code is due to use of GOTO -- so why is it that so many people seem to believe these myths? It was Dijsktra [sp?]. Other than that, I perfectly agree! +---------------------------+------------------------+-------------------+ | Anton Rang (grad student) | "VMS Forever!" | VOTE on | | Michigan State University | rang@cpswh.cps.msu.edu | rec.music.newage! | +---------------------------+------------------------+-------------------+ | Send votes for/against rec.music.newage to "rang@cpswh.cps.msu.edu". | +---------------------------+------------------------+-------------------+
jlg@lanl.gov (Jim Giles) (05/05/89)
From article <1814@ubu.warwick.UUCP>, by mirk@warwick.UUCP (Mike Taylor): > printf ("Enter your sex: "); > LABEL: gets (sex); > if (sex != "m" && sex != "f") { > printf ("<m> or <f> only: "); > GOTO LABEL; > } > > Better examples abound, but in time honoured way, elude me now that I > need them. How many times have you seen people using "for (;;;) ... > break;" when you *know* that by "break" they mean "GOTO"? Actually, in the above example, "break" is a better way. This is the classic "loop and a half" problem for which the "break" statement exists. So the following is a better suggestion: printf ("Enter your sex: "); for (;;) { gets (sex); if (sex == "m" || sex == "f") break; printf ("<m> or <f> only: "); } Note: since C doesn't have multi-level breaks, GOTO must be used to escape from nested constructs. This does not mean that I oppose GOTOs in a programming language. In fact, there _are_ situations in which GOTO is the most readible and efficient means of flow control. Consider the situation in which two branches of a conditional merge again: if (cond1) { [...A...] /* lots of code */ goto LABEL;} else if (cond2) { LABEL: [...B...] /* lots more code */ } After executing sequence 'A', the rest of the action for 'cond1' is identical to the action for 'cond2'. The suggested "structured" fixes to this sequence include: 1) put sequence 'B' in a separate procedure and call it from both places 2) duplicate sequence 'b' in both places 3) set a flag variable to hold the condition that 'B' needs to be executed, and put 'B' after the original 'if' sequence enclosed in another conditional. The problem with 1) is that it introduces a speed penalties due to the procedure call - not efficient. Solution 2) imposes a code space penalty as well as making code maintenance difficult (you must always remember to update _both_ versions of 'B'). Solution 3) imposes a speed penalty for setting and testing the flag, a space penalty for the extra variable and the code to manipulate it, and it is _less_ readible than the version already given above! This conditional-merge problem is one of the only two places where I still use GOTO in my programs - the other case is the classic error-exit from deep within a nested structure (exception handling, if available, would satisfy this requirement). Unfortunately, the above construct is illegal in many "structured" programming languages (including - of all things - Fortran). They seem to feel that jumping into a compound statement from the outside is bad practice. Yet, I run into this case all the time (even on very short programs (<1000 lines) I usually run into this at least once). And there is no "structured" way around it! Note: I always make a distinction between well structured programs and well "structured" programs. The later are those which conform to the anti-GOTO religion without regard to the actual quality of the code itself. A well "structured" program is often a very badly structured one.
jik@athena.mit.edu (Jonathan I. Kamens) (05/05/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: >How many times have you seen this kind of code? > > printf ("Enter your sex: "); > while (sex != "m" && sex != "f") { > gets (sex); > if (sex != "m" && sex != "f") > printf ("<m> or <f> only: "); > } Indeed, this is a pretty bad example of where a goto would be useful, because you are simply illustrating what the purpose of the C do ... while construct is for: do { fprintf(stdout, "Enter your sex (<m> or <f> only): "); fflush(stdout); fgets(stdin, sex, 2); fflush(stdin); } while ((*sex != 'm') && (*sex != 'f')); Granted, goto can have its uses, and exception handling is a prime example, but don't go jumping to conclusions and saying that goto is the most understandable method to use in a case where (at least in my opinion) a more "structured" construct does a better job. Jonathan Kamens USnail: MIT Project Athena 410 Memorial Drive, No. 223F jik@Athena.MIT.EDU Cambridge, MA 02139-4318 Office: 617-253-4261 Home: 617-225-8218
rang@cpsin3.cps.msu.edu (Anton Rang) (05/05/89)
In article <13113@lanl.gov> jlg@lanl.gov (Jim Giles) writes: > Actually, in the above example, "break" is a better way. This is the > classic "loop and a half" problem for which the "break" statement > exists. So the following is a better suggestion: > > printf ("Enter your sex: "); > for (;;) { > gets (sex); > if (sex == "m" || sex == "f") break; > printf ("<m> or <f> only: "); > } > > Note: since C doesn't have multi-level breaks, GOTO must be used to escape > from nested constructs. This is ugly; it essentially transforms the code LABEL: get input if (bad input) print message go back to label into LABEL: get input if (good input) goto LABEL2 print message go back to label LABEL2: Now you have two places where control jumps around, instead of just one. 'break' has its uses, perhaps, but this isn't one of them (IMHO). Actually, I feel that 'break' should usually be replaced by an explicit goto (heresy!). Why? Because the place the break goes to isn't explicit; you have to start matching up loops. If you have lots of nesting, this is quite a mess. Named loops in Ada are intended to alleviate this problem, and if used properly seem to do a decent job. +---------------------------+------------------------+-------------------+ | Anton Rang (grad student) | "VMS Forever!" | VOTE on | | Michigan State University | rang@cpswh.cps.msu.edu | rec.music.newage! | +---------------------------+------------------------+-------------------+ | Send votes for/against rec.music.newage to "rang@cpswh.cps.msu.edu". | +---------------------------+------------------------+-------------------+
ked@garnet.berkeley.edu (Earl H. Kinmonth) (05/05/89)
Keywords: Guinness, phlegm, mackerel, intestines >magic wand over a language by excising GOTO, and everything will be >alright. Listen, just 'cause Quiche-eater Wirth connected GOTOs with >lack of structure geenrally, doesn't mean either that (A) ALL use of >GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code >is due to use of GOTO -- so why is it that so many people seem to I began programming in 1968 on a CDC 1604. I used Fortran (when the sucker did not force me to use binary). Thus, I am more than familiar with the go to statement (including the conditional go to statement). Since 1979 I have been programming in C. I have written C code into the high six-figures (lines of code). There has not been one case where a goto seemed appropriate. When I was tempted, reflection and analysis convinced me that a goto solution was inappropriate. This is not a quiche-eater's problem. I teach Japanese history by profession, and could give a s__t one way or the other. I want code that is efficient (where efficiency includes my time) and that I have some hope of understanding a few months or years down the line. By my standards, the goto s__ks. Some months ago, I rewrote GNUtar (an early version) to run under MSDOS. The original author, in the name of "efficiency" had used a large number of goto(s). As is common with such programming, he had not used prof to find out whether the goto really resulted in faster execution. He had, however, succeeded in making the code extremely difficult to read. As for the example that was part of this original posting, the author should learn to use the switch statement. The switch in C is in effect a "conditonal goto" (to use the jargon I learned with the 1604 in 1968), but it is much, much easier to read. Since my specialty is Japanese history (albeit built on an undergrad education in EE), I probably should not be telling !!!!!PROGRAMMERS!!!!! (bells, gongs, drum rolls, trumpet flourishes) how to do their work. Based on substantial experience, I would nevertheless suggest that if you are absolutely convinced of the need for a goto, that section of the code should really be done in assembler.
ked@garnet.berkeley.edu (Earl H. Kinmonth) (05/05/89)
>Indeed, this is a pretty bad example of where a goto would be useful, >because you are simply illustrating what the purpose of the C do ... >while construct is for: > >do { > fprintf(stdout, "Enter your sex (<m> or <f> only): "); > fflush(stdout); > fgets(stdin, sex, 2); > fflush(stdin); >} while ((*sex != 'm') && (*sex != 'f')); First, your C compiler must have a rather weird stdio library if it requires you to to do explicit flushing. Second, why not while(1) { fputs("Sex (m or f) ",stdout); gets(ls); if(ls[0] == 'm') return(ls[0]); else if(ls[0] == 'f') return(ls[0]); } as a subroutine?
tale@pawl.rpi.edu (David C Lawrence) (05/05/89)
In article <24047@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: > Second, why not > ... [ deleted ] ... > gets(ls); > ... [ deleted ] ... > as a subroutine? Because gets() is almost as evil as goto(). Can we say Internet Worm? Dave -- tale@rpitsmts.bitnet, tale%mts@itsgw.rpi.edu, tale@pawl.rpi.edu
falk@sun.Eng.Sun.COM (Ed Falk) (05/05/89)
In article <24047@agate.BERKELEY.EDU>, ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: > > Second, why not > > while(1) { > fputs("Sex (m or f) ",stdout); > gets(ls); > if(ls[0] == 'm') return(ls[0]); > else > if(ls[0] == 'f') return(ls[0]); > } > > as a subroutine? YUK! This is getting worse and worse. A "return" is basicly a GOTO to the end of the function. Besides being nit-picky, there's a LOT of reasons not to put returns in the middle of code; you're sure to get bitten by that habit. Supposing you later come back and modify this function to allocate some resource and then free it at the end before returning. If you don't notice a return in the middle of your code, you start eating resources. -- -ed falk, sun microsystems sun!falk, falk@sun.com card-carrying ACLU member.
arrom@aplcen.apl.jhu.edu (Ken Arromdee) (05/05/89)
>> printf ("Enter your sex: "); >> while (sex != "m" && sex != "f") { >> gets (sex); >> if (sex != "m" && sex != "f") >> printf ("<m> or <f> only: "); >> } >do { > fprintf(stdout, "Enter your sex (<m> or <f> only): "); > fflush(stdout); > fgets(stdin, sex, 2); > fflush(stdin); >} while ((*sex != 'm') && (*sex != 'f')); This is not analogous. The original example prints the "<m> or <f> only:" message only if the input is not an "m" or "f". This supposeedly analogous program prints it every time. I _know_ I can change the > but beating inews this way _feels_ better... -- "Do you know what this is????" "No, what?" "I don't know either..." -- Who said it, what story? Kenneth Arromdee (UUCP: ....!jhunix!ins_akaa; BITNET: g49i0188@jhuvm; INTERNET: arromdee@crabcake.cs.jhu.edu) (please, no mail to arrom@aplcen)
kers@otter.hpl.hp.com (Chris Dollin) (05/05/89)
Mike Taylor said: (In an probably fruitless attempt to stem a public GOTO war, I am prepared to have a private email war with Mike and report back later - see end of article.) | In article <3, I think> gould@rosemary.cs.reading.ac.uk (Adrian Gould) writes: | > Lets eradicate the GOTO from all languages. | | I hate it when people say things like that; As if you can just wave a | magic wand over a language by excising GOTO, and everything will be | alright. Listen, just 'cause Quiche-eater Wirth connected GOTOs with | lack of structure geenrally, doesn't mean either that (A) ALL use of | GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code | is due to use of GOTO -- so why is it that so many people seem to | believe these myths? | | How many times have you seen this kind of code? | | printf ("Enter your sex: "); | while (sex != "m" && sex != "f") { | gets (sex); | if (sex != "m" && sex != "f") | printf ("<m> or <f> only: "); | } | Not very often. | Why make the test twice? Huh? Huh? Answer me that, all you obsessed | anti-GOTO campaigners. The *natural* way to express the above is: | | printf ("Enter your sex: "); | LABEL: gets (sex); | if (sex != "m" && sex != "f") { | printf ("<m> or <f> only: "); | GOTO LABEL; | } I don't know about "natural". Is programming "natural"? But, using the word within the meaning of the Act, I'd say the natural way to write this is: printf( "Enter your sex: "); repeat gets( sex ); until sex == "m" or sex == "f"; printf( "<m> or <f> only: " ) endrepeat; Of course, if you want to write it like this in C, you'd have to do something like: PROMPT; /* Stuff it, I'm not writing it */ while( GETS, CONDITION ) REPROMPT; /* out all over again. */ Structured programming is not about omitting GOTOs, but using control structures suitable for the task at hand. The idiom you mention is usually called the "N-and-a-half-times loop", and should damn well be supported in *any* imperative programming language. Tell you what, Mike; mail me and we'll talk about this without cluttering the net. Then we can summarise our battle - ahem, enlightened debate - later.
ken@aiai.ed.ac.uk (Ken Johnson) (05/05/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: >How many times have you seen this kind of code? > > printf ("Enter your sex: "); > while (sex != "m" && sex != "f") { > gets (sex); > if (sex != "m" && sex != "f") > printf ("<m> or <f> only: "); > } > I like doing it this way: (NB This is not correct C! But I think it is a correct program structure for the problem.) get_sex( ) { return(get_sex_sub("Enter your sex: ")); } get_sex_sub(string) { printf (string); gets(sex) return( (sex == 'm' || sex == 'f') ? sex : get_sex_sub("<m> or <f> only: ") ); } -- Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212 Annoy the Labour Party! Pay the Poll Tax!
jha@lfcs.ed.ac.uk (Jamie Andrews) (05/05/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: >Why make the test twice? Huh? Huh? Answer me that, all you obsessed >anti-GOTO campaigners. The *natural* way to express the above is: > > printf ("Enter your sex: "); >LABEL: gets (sex); > if (sex != "m" && sex != "f") { > printf ("<m> or <f> only: "); > GOTO LABEL; > } Death to GOTO! printf ("Enter your sex: "); while (1) { gets (sex); if (sex == "m" || sex == "f") break; else printf ("<m> or <f> only: "); } Long live break! --J.
lishka@uwslh.UUCP (a.k.a. Fish-Guts) (05/05/89)
In article <24044@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: > >Since 1979 I have been programming in C. I have written C code into the >high six-figures (lines of code). There has not been one case where a >goto seemed appropriate. When I was tempted, reflection and analysis >convinced me that a goto solution was inappropriate. You may not have been writing code where "goto"'s can be a life saver. Here are two quotes from the writers of C and C++ on where goto's are actually useful: From _The_C_Programming_Language_ by B. Kernighan & D. Ritchie: C provides the infinitely-abusable _goto_ statement, and labels to branch to. Formally, the _goto_ is never necessary, and in practice it is almost always easy to write code without it. We have not used _goto_ in this book. Nonetheless, we will suggest a few situations where _goto_'s may find a place. The most common use is to abandon processing in some deeply nested structure, such as breaking out of two loops at once. The _break_ statement cannot be used directly since it leaves only the innermost loop [...]. This organization is handy if the error-handling code is non-trivial, and if errors can occur in several places. [...] Code involving a _goto_ can always be written without one, though perhaps at the price of some repeated tests an extra variable. [...] Although we are not dogmatic about the matter, it does seem that _goto_ statements should be used sparingly, if at all. From _The_C++_Programming_Language_ by B. Stroustrup: C++ possesses the infamous _goto_. [...] It has few uses in general high-level programming, but it can be very useful when a C++ program is generated by a program rather than written directly by a person [...]. The _goto_ can also be important in the rare cases when optimal efficiency is essential [..]. One of the few sensible uses of the _goto_ is to break out from a nested loop or switch [...]. So there are the comments, "straight from the horses' mouthes!" There are times (especially when writing recursive-descent compilers) when the use of one _goto_ or longjmp() can save many, many additional tests. Note that the setjmp()/longjmp() functions are just a _goto_/label equivalent that can jump across functions (by unwinding the stack). _Goto_ does have its place! >Some months ago, I rewrote GNUtar (an early version) to run under >MSDOS. The original author, in the name of "efficiency" had used a >large number of goto(s). As is common with such programming, he had not >used prof to find out whether the goto really resulted in faster >execution. He had, however, succeeded in making the code extremely >difficult to read. Goto, as implemented in an IBM PC compiler, may not be as efficient in some memory models as the equivalent code without goto's (because a jump across segments might be necessary). However, goto's can be much more efficient when all that is needed is a single assembler instruction to implement the goto (I oughta know: I had to implement this in an Ada-subset compiler for a graduate compiler course). >As for the example that was part of this original posting, the author >should learn to use the switch statement. The switch in C is in effect >a "conditonal goto" (to use the jargon I learned with the 1604 in >1968), but it is much, much easier to read. The _switch_ statement is a "conditional goto," but only for constants. Much better is the (cond ...) conditional statement in Lisp, or the _case_ statement in Ada. There are many times when I wish C would allow variables (and not just constants) after the _case_ keywords! >Since my specialty is Japanese history (albeit built on an undergrad >education in EE), I probably should not be telling >!!!!!PROGRAMMERS!!!!! (bells, gongs, drum rolls, trumpet flourishes) >how to do their work. You seem to have more experience writing code than many "programmers," and your comments are good. However, I still maintain that there are some cases where good use of a goto can make code much more "readable," and can save a helluva lot of additional tests that shouldn't be necessary. As long as it is not abused, _goto_ and setjmp()/longjmp() can be very useful. >Based on substantial experience, I would >nevertheless suggest that if you are absolutely convinced of the need >for a goto, that section of the code should really be done in >assembler. Talk about making the code unreadable by using a _goto_! Including assembler in a C program will really make it unreadable.-- Christopher Lishka ...!{rutgers|ucbvax|...}!uwvax!uwslh!lishka Wisconsin State Lab of Hygiene lishka%uwslh.uucp@cs.wisc.edu Immunology Section (608)262-1617 lishka@uwslh.uucp "I'm not aware of too many things... I know what I know if you know what I mean" -- Edie Brickell & New Bohemians
rang@cpsin3.cps.msu.edu (Anton Rang) (05/05/89)
In article <24044@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: >Since 1979 I have been programming in C. I have written C code into the >high six-figures (lines of code). There has not been one case where a >goto seemed appropriate. When I was tempted, reflection and analysis >convinced me that a goto solution was inappropriate. Not one case? I haven't been programming in C that long, but I've run into cases where a 'goto' is clearer than any of the other solutions. There is usually another way to do it, but often the goto seems best (especially for exception handling, though not always). Partly, this is because I dislike some of C's "features". Returning from the middle of a function fred() is "more evil" (IMHO) than making a label "end_of_fred" and using "goto end_of_fred". Why? Because there is only one entry to and exit from the function (as somebody else pointed out, this is useful if you're allocating resources etc.) Using "break" is OK for small loops, but not good for huge ones. Why? You can't tell where the break goes without going through the loop, balancing "{" and "}". Also, if you ever move the code with the break into another loop, you're now breaking from the wrong loop! Named loops, or labels "end_while_n_loop" avoid this problem. Exception handling is the worst problem. I used to write functions which had millions of nested if statements, because I had been thoroughly indoctrinated with "GOTO is EVIL!". I'd write code that would be "call function. If success, { call function. If success, { call function. [ ad infinitum ] } } " . Much easier to have a label at the end of the function to handle it--easier to write, easier to read, and much easier to change. Incidentally, using GOTO in these ways--always to get out of a structure--doesn't seriously hurt compiler optimization, because you shouldn't be breaking up basic blocks in the process (jumping into the middle of a sequence of statements is what's evil, GOTO's not evil). > Based on substantial experience, I would >nevertheless suggest that if you are absolutely convinced of the need >for a goto, that section of the code should really be done in >assembler. Assembler??? Why should I sacrifice readability, and (some) portability, just because I need (or want) a "goto"? +---------------------------+------------------------+-------------------+ | Anton Rang (grad student) | "VMS Forever!" | VOTE on | | Michigan State University | rang@cpswh.cps.msu.edu | rec.music.newage! | +---------------------------+------------------------+-------------------+ | Send votes for/against rec.music.newage to "rang@cpswh.cps.msu.edu". | +---------------------------+------------------------+-------------------+
hollombe@ttidca.TTI.COM (The Polymath) (05/06/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: }In article <3, I think> gould@rosemary.cs.reading.ac.uk (Adrian Gould) writes: }> Lets eradicate the GOTO from all languages. } }I hate it when people say things like that; As if you can just wave a }magic wand over a language by excising GOTO, and everything will be }alright. Listen, just 'cause Quiche-eater Wirth connected GOTOs with It was Dijkstra. }lack of structure geenrally, doesn't mean either that (A) ALL use of }GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code }is due to use of GOTO ... }How many times have you seen this kind of code? } } printf ("Enter your sex: "); } while (sex != "m" && sex != "f") { } gets (sex); } if (sex != "m" && sex != "f") } printf ("<m> or <f> only: "); } } } Thankfully, not very often (but then, I haven't got around to teaching an intro to programming course, yet). Here's how it should be done: do { printf ("\nEnter your sex (m or f): ") if (EOF == (sex = getchar()) perror ("getchar() error"); } while ((sex != 'm') && (sex != 'f')) Generally, a little thought and analysis can eliminate the need for nearly all GOTOs quite elegantly. }... How many times have you seen people using "for (;;;) ... }break;" when you *know* that by "break" they mean "GOTO"? ... If they'd meant goto they'd have said goto. The construct does exist in C. "break" is not equivalent. It's much more limited and less likely to get you into trouble. }... In many }situations GOTO is natural ... In a few situations it has its uses. }... Clearly irresponsible use of }GOTO is bad; clearly spaghetti-junction programs written in languages }with no other flow-control are bad (Frog knows how APL people manage!) }But let's get this in perspective. It isn't GOTO's fault. It's yours }for using it badly. True. The best quote I've heard on the subject was from some CS lecturer: "I sometimes use GOTOs. I also use guns. I _don't_ let children play with them." }It makes me laugh when people push Ada as a good real-time langauge }because iof its "powerful exception-handling". "Exception-handling". }Do you know what that means? Yup, you guessed it, it's a fancy word }for GOTO. ... No, it isn't. As I recall, it's much closer to return(). An Ada function either has its own exception handler or it passes the exception back to the function that called it. -- The Polymath (aka: Jerry Hollombe, hollombe@ttidca.tti.com) Illegitimati Nil Citicorp(+)TTI Carborundum 3100 Ocean Park Blvd. (213) 452-9191, x2483 Santa Monica, CA 90405 {csun|philabs|psivax}!ttidca!hollombe
cetron@wasatch.utah.edu (Edward J Cetron) (05/06/89)
>from the middle of a function fred() is "more evil" (IMHO) than making >a label "end_of_fred" and using "goto end_of_fred". Why? Because >there is only one entry to and exit from the function (as somebody >else pointed out, this is useful if you're allocating resources etc.) good point > Incidentally, using GOTO in these ways--always to get out of a >structure--doesn't seriously hurt compiler optimization, because you >shouldn't be breaking up basic blocks in the process (jumping into the >middle of a sequence of statements is what's evil, GOTO's not evil). > another good point > > Assembler??? Why should I sacrifice readability, and (some) >portability, just because I need (or want) a "goto"? > >| Anton Rang (grad student) | "VMS Forever!" | VOTE on | This entire GOTO debate seems to be indicative of the quality of programmers currently available today. To them, STRUCTURE is EVERYTHING. They've even forgotten (or never learned WHY structured concepts are good). But MOST IMPORTANTLY the forget that somewhere, somehow, a computer HAS to execute these programs. Before I ever was taught about programming, I was taught how the computers worked at the machine code level. If once only considers the computer at the HLL level, no matter how good and optimizing compiler you have, you can still write stuff that is damned inefficient. Maybe all these anti-GOTOites only write big COBOL programs which are only used for Public Utility billing activities :-). No matter what your code is like in a HLL, it is STILL just a GOTO (JMP, BR, RTS...) to the CPU. We've bred an entire generation of programmers and CS students who are so concerned with 'ADA is better than C, and FORTRAN sucks' and 'STRUCTURE is all that matters' and 'UNIX is it' that they have forgotten why programs are written in the first place. They sit in their " programmers' ivory tower" and forget that the program is supposed to do something in reality! I would rather have a clearly written program (structured or not) which accomplishes what the PROGRAM is intended to do, without excess baggage and }'s JUST to satisfy some STRUCTURED PROGRAMMING GOD, with GOTO's when necessary, AND WHICH SHOW SOME UNDERSTANDING OF THE COMPUTER UNDER WHICH IT WILL RUN, than some beautiful piece of code which when compiled/linked is nothing but dribble to the CPU anyway. Maybe that's why I only hire hardware oriented people. You can teach a h/w person to program, but most s/w types are confused by hardware. I'm not saying I prefer to code in assembler, but that one MUST know one's environment. It does not good to write exquisite Latin prose if your audience speaks Chinese. Sorry for the flame, I'm just tired of interviewing smug new CS students who know nothing about reality and using the right tools for the job. They make great followers, but we desparately need thinkers and leaders. -ed cetron cetron@wasatch.utah.edu
jlg@lanl.gov (Jim Giles) (05/06/89)
From article <2854@cps3xx.UUCP>, by rang@cpsin3.cps.msu.edu (Anton Rang): >> printf ("Enter your sex: "); >> for (;;) { >> gets (sex); >> if (sex == "m" || sex == "f") break; >> printf ("<m> or <f> only: "); >> } > This is ugly; it essentially transforms the code > [...] > into > > LABEL: get input > if (good input) > goto LABEL2 > print message > go back to label > LABEL2: You are exactly right. I didn't say the feature was elegant, I said that "loop-and-a-half" problems were the reason that "break" was introduced into looping constructs (which occured in languages long before C was invented). The reason for "break" in "case" constructs only dmr can answer 8-). > [...] Because the place the break goes to > isn't explicit; you have to start matching up loops. If you have lots > of nesting, this is quite a mess. > Named loops in Ada are intended to alleviate this problem, and if > used properly seem to do a decent job. I like the solution of named loops too. But Ada puts all but the first occurrance of the the label into the code rather than on the left margin. The advantage of GOTOs (if any) was that you could easily find the target of the branch by looking for the label. Consider the example on page 5-8 of the Ada standard: MAIN_CYCLE: loop -- initial statements exit MAIN_CYCLE when FOUND; -- final statements end loop MAIN_CYCLE; If the "initial" and "final" statement sequences were long and complicated the "exit" and "end loop" could be difficult to identify. (Even indentation only helps a little if the code crosses page boundaries.) In the Nemesis programming language the above loop would be rendered as: MAIN_CYCLE: do -- initial statements MAIN_CYCLE: exit if (FOUND) -- final statements MAIN_CYCLE: end do Here, no matter how long and complicated the statement sequences are, all the controls for the "MAIN_CYCLE" loop are easily identified by scanning the left margin of the code. Note that the identifier "MAIN_CYCLE" is the _name_ of a loop and _not_ a statement label (you can't GOTO MAIN_CYCLE). Loop names _must_ appear on all control statements for the loop. Unnamed loops are allowed and must _not_ have a name on any control statement.
mark@cygnet.CYGNETSYSTEMS (Mark Quattrocchi) (05/06/89)
In article <11136@bloom-beacon.MIT.EDU> jik@athena.mit.edu (Jonathan I. Kamens) writes: >In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: >>How many times have you seen this kind of code? >> >> printf ("Enter your sex: "); >> while (sex != "m" && sex != "f") { >> gets (sex); >> if (sex != "m" && sex != "f") >> printf ("<m> or <f> only: "); >> } > >Indeed, this is a pretty bad example of where a goto would be useful, >because you are simply illustrating what the purpose of the C do ... >while construct is for: > >do { > fprintf(stdout, "Enter your sex (<m> or <f> only): "); > fflush(stdout); > fgets(stdin, sex, 2); > fflush(stdin); >} while ((*sex != 'm') && (*sex != 'f')); > >Granted, goto can have its uses, and exception handling is a prime >example, but don't go jumping to conclusions and saying that goto is >the most understandable method to use in a case where (at least in my >opinion) a more "structured" construct does a better job. > Speaking of jumping to conclusions, your code is not a one for one equivalent of the original. Even though I agree with your interpretation, you are cheating by combining the print statements together. Try again only don't cheat.
mark@cygnet.CYGNETSYSTEMS (Mark Quattrocchi) (05/06/89)
In article <24047@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: >>Indeed, this is a pretty bad example of where a goto would be useful, >>because you are simply illustrating what the purpose of the C do ... >>while construct is for: >> >>do { >> fprintf(stdout, "Enter your sex (<m> or <f> only): "); >> fflush(stdout); >> fgets(stdin, sex, 2); >> fflush(stdin); >>} while ((*sex != 'm') && (*sex != 'f')); > >First, your C compiler must have a rather weird stdio library if it >requires you to to do explicit flushing. > >Second, why not > > while(1) { > fputs("Sex (m or f) ",stdout); > gets(ls); > if(ls[0] == 'm') return(ls[0]); > else > if(ls[0] == 'f') return(ls[0]); > } > >as a subroutine? This is great! Now we have two incorrect versions. Open eyes, read original, duplicate. I suppose they did this because the program would be twice as long if they made it compatible with the original. Sorry, just testing our newsfeed (yeah that's it).
bill@twwells.uucp (T. William Wells) (05/07/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: : How many times have you seen this kind of code? : : printf ("Enter your sex: "); : while (sex != "m" && sex != "f") { : gets (sex); : if (sex != "m" && sex != "f") : printf ("<m> or <f> only: "); : } : : Why make the test twice? Huh? Huh? Answer me that, all you obsessed : anti-GOTO campaigners. The *natural* way to express the above is: : : printf ("Enter your sex: "); : LABEL: gets (sex); : if (sex != "m" && sex != "f") { : printf ("<m> or <f> only: "); : GOTO LABEL; : } Why not: printf("Enter your sex: "); while (1) { gets(sex); if (sex == "m" || sex == "f") break; } printf("<m> or <f> only: "); } While it is might be the case that some things are better coded with gotos than not, I've not seen any in many years of C programming. : need them. How many times have you seen people using "for (;;;) ... : break;" when you *know* that by "break" they mean "GOTO"? In many Eh, sonny? The point of the break is that you *know* that it is a goto, _and that you know where it is going *to*_. : It makes me laugh when people push Ada as a good real-time langauge : because iof its "powerful exception-handling". "Exception-handling". : Do you know what that means? Yup, you guessed it, it's a fancy word : for GOTO. Luverly, Eh? Dress it up to look nice'n'respectable, : install it as a fabulous feature in a DoD-sponsored langauge-to-end- : all-languages, and everyone loves it. Well they ain't fooling me. : I know goto when I see it. *Every* control structure is a dressed-up goto. The point of the control structures is to dress up the gotos so that you know what they are *for*. Here. I'll dig into my archives, and give you the following: From novavax!uflorida!proxftl.UUCP!bill Thu May 19 15:52:54 1988 Path: proxftl!bill From: bill@proxftl.UUCP (T. William Wells) Newsgroups: comp.lang.c Subject: Re: gotos Summary: talking about gotos is fruitless Message-ID: <197@proxftl.UUCP> Date: 19 May 88 19:52:54 GMT References: <1988Apr8.183815.3187@utzoo.uucp>, <449@goofy.megatest.UUCP> <528@wsccs.UUCP> Organization: Proximity Technology, Ft. Lauderdale Lines: 129 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 have programmed in C for six years now and have NEVER used a goto. We have uncounted megabytes of C code written in-house. None of it (to my knowledge) contains a goto. The closest thing we have to a goto is setjmp/longjmp, used to implement a multi-level return (and that is a recent change, one whose contemplation caused much debate). 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. The 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 would be implemented with a goto), I have never had need of one. Given the amount of code I write, it seems to me that one might never need to use an explicit goto in C code. Now that I think of it, here is a reason to avoid naked gotos in C code: for all other constructs, the control structure being implemented is obvious from the keywords employed. This is not true for goto. Therefore, supposing that you have found a control structure that you have to implement using gotos in C, you should dress the goto up. 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 the macros state and nextstate being used, you will be seeing a state machine. The state macro defines the start of a state. The nextstate macro causes a transfer of control to another state of the same machine. A state machine starts at a #define of statepref and ends with state(DONE). */ #define dummy(x) x #define state(x) dummy(statepref)x #define nextstate(x) goto dummy(statepref)x #ifdef statepref #undef statepref #endif #define statepref STATE_ state(INIT): ... code for this state nextstate(DONE); ... more states with the appropriate code state(DONE): ... code after the state machine (N.B. I am aware that not all preprocessors will do what I want here; for real portability, you would explicitly write the prefixes. Also, this method fails for nested state machines, something I have occasionally had need of.) 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. (After all, a while is just a disguised goto :-)
bill@twwells.uucp (T. William Wells) (05/07/89)
In article <13113@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
: This does not mean that I oppose GOTOs in a programming language. In fact,
: there _are_ situations in which GOTO is the most readible and efficient
: means of flow control. Consider the situation in which two branches of
: a conditional merge again:
:
: if (cond1) {
: [...A...] /* lots of code */
: goto LABEL;}
: else if (cond2) {
: LABEL: [...B...] /* lots more code */
: }
:
: After executing sequence 'A', the rest of the action for 'cond1' is identical
: to the action for 'cond2'. The suggested "structured" fixes to this sequence
: include:
: 1) put sequence 'B' in a separate procedure and call it from both places
:
: 2) duplicate sequence 'b' in both places
:
: 3) set a flag variable to hold the condition that 'B' needs to be
: executed, and put 'B' after the original 'if' sequence enclosed
: in another conditional.
:
: The problem with 1) is that it introduces a speed penalties due to the
: procedure call - not efficient.
Agreed. Until the amount of code overwhelms the function call
overhead.
: Solution 2) imposes a code space penalty
: as well as making code maintenance difficult (you must always remember to
: update _both_ versions of 'B').
Only half true. Many (most?) optimizers will recognize that the two
code sequences are identical and put the branch where you would
expect.
: Solution 3) imposes a speed penalty for
: setting and testing the flag, a space penalty for the extra variable and
: the code to manipulate it, and it is _less_ readible than the version
: already given above!
Damn straight!
: This conditional-merge problem is one of the only two places where I still
: use GOTO in my programs - the other case is the classic error-exit from
: deep within a nested structure (exception handling, if available, would
: satisfy this requirement).
Be aware that a *single* goto in a function can cause many optimizers
to do nothing for the function. The reason for this is that many of
the better optimization techniques depend on the program having a
particular control structure and transforming an arbitrary program
into one that is acceptable is a hairy task.
: Unfortunately, the above construct is illegal in many "structured"
: programming languages (including - of all things - Fortran). They seem
: to feel that jumping into a compound statement from the outside is
: bad practice. Yet, I run into this case all the time (even on very short
: programs (<1000 lines) I usually run into this at least once). And there
: is no "structured" way around it!
Me, I just live with the possible code duplication; the maintenance
headache is minor. By the time the code is large enough to make both
considerations less than minor, the function call overhead has become
trivial.
: Note: I always make a distinction between well structured programs and
: well "structured" programs. The later are those which conform to the
: anti-GOTO religion without regard to the actual quality of the code
: itself. A well "structured" program is often a very badly structured
: one.
Some of the worst structured programs I've seen have been written in
Modula 2. Some people think that merely following the structured
programming rules relieves them from the responsibility to think.
---
Bill { uunet | novavax } !twwells!bill
bill@twwells.uucp (T. William Wells) (05/07/89)
In article <2854@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: : In article <13113@lanl.gov> jlg@lanl.gov (Jim Giles) writes: : > printf ("Enter your sex: "); : > for (;;) { : > gets (sex); : > if (sex == "m" || sex == "f") break; : > printf ("<m> or <f> only: "); : > } : This is ugly; it essentially transforms the code : : LABEL: get input : if (bad input) : print message : go back to label : : into : : LABEL: get input : if (good input) : goto LABEL2 : print message : go back to label : LABEL2: Silly boy! No one gives a f*** how the code gets transformed. All we have to read is the original. And the original is simplicity itself. Would you please return to your ideological teachers and not bother us with such irrelevancies? : Now you have two places where control jumps around, instead of just : one. 'break' has its uses, perhaps, but this isn't one of them : (IMHO). Actually, I feel that 'break' should usually be replaced by : an explicit goto (heresy!). Why? Because the place the break goes to : isn't explicit; you have to start matching up loops. If you have lots : of nesting, this is quite a mess. By this you demonstrate that you have nothing worthwhile to say on the subject. You just don't understand the problem. Hell, you are *part* of the problem. Followups have been directed to alt.flame. --- Bill { uunet | novavax } !twwells!bill
bill@twwells.uucp (T. William Wells) (05/07/89)
In article <103199@sun.Eng.Sun.COM> falk@sun.Eng.Sun.COM (Ed Falk) writes:
: YUK! This is getting worse and worse. A "return" is basicly a
: GOTO to the end of the function. Besides being nit-picky, there's
: a LOT of reasons not to put returns in the middle of code; you're
: sure to get bitten by that habit. Supposing you later come back
: and modify this function to allocate some resource and then free it
: at the end before returning. If you don't notice a return in the
: middle of your code, you start eating resources.
Not reasonable. The "search" key in your favorite editor will easily
spot return. A failure to look for them is simply bad programming.
No, this is yet another example of misguided structured programming
ideology; the reasons for this went away when punch cards ceased to
be the normal method of entering programs.
---
Bill { uunet | novavax } !twwells!bill
jejones@mcrware.UUCP (James Jones) (05/07/89)
In article <1384@cygnet.CYGNETSYSTEMS> mark@cygnet.UUCP (Mark Quattrocchi) writes: >This is great! Now we have two incorrect versions. Open eyes, read original, >duplicate. I suppose they did this because the program would be twice as long >if they made it compatible with the original. /* Sorry, I couldn't resist changing the prompt... :-) */ printf("I want your sex: "); while (gets(answer), (answer[0] != 'm' && answer[0] != 'f')) printf("<m> or <f> only: "); Admittedly (1) this version, like most of those I've seen so far, evades the question of gets() failure (though unlike the original version, it does *not* test the input before it's been read!), and it does presume that stdout is unbuffered so that the user sees the prompt (like the original) (2) if the preparation for the checking were very much more complicated, one would have to drop back to using a break statement (where's Algol 68 when you really need it?) (3) the *true* dammit-structured-programming-is-a-hoax-and-only-good-enough- for-quiche-eaters-who-can't-really-program type would still object to this code because this loop may be followed by a redundant test of answer[0]! and indeed, the objection in (3) could be a reasonable one, if the test for validity were particularly complicated. Let's all go read or reread Knuth, "Structured programming with goto statements" (*Computing Surveys*, December 1974), so we can stop flogging this dead horse, OK? It hasn't *quite* been 25 years since Dijkstra's famous letter, but it's close. James Jones
jik@athena.mit.edu (Jonathan I. Kamens) (05/08/89)
In article <24047@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: >First, your C compiler must have a rather weird stdio library if it >requires you to to do explicit flushing. Some stdio libraries do not flush stdout unless you print a newline, and when you are prompting for input you usually do not follow the prompt with a newline. Further, I flushed stdin because I wanted to be consistent :-) -- it probably wan't necessary. >Second, why not > > ... > >as a subroutine? My point was not that the code segment I posted was the *best* way to do the job, but rather that it was one way to do it that did not require goto's. You have shown another way. As for why not as a subroutine, if you're only doing it once then using a subroutine is a speed hit that you don't need (a small speed hit, granted, but a speed hit nevertheless :-). Inlining makes it run faster. You're suggestion is similar to the suggestion someone else posted of using break to exit the loop when valid input was obtained. Jonathan Kamens USnail: MIT Project Athena 410 Memorial Drive, No. 223F jik@Athena.MIT.EDU Cambridge, MA 02139-4318 Office: 617-253-4261 Home: 617-225-8218
ked@garnet.berkeley.edu (Earl H. Kinmonth) (05/08/89)
In article <11197@bloom-beacon.MIT.EDU> jik@athena.mit.edu (Jonathan I. Kamens) writes: >In article <24047@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: >As for why not as a subroutine, if you're only doing it once then >using a subroutine is a speed hit that you don't need (a small speed >hit, granted, but a speed hit nevertheless :-). Inlining makes it run >faster. Please run this one past me again. Since I'm an historian and not a programmer my mind must work differently. If you are doing it only once and only micro-seconds are involved, the clearest form should prevail (a subroutine rather than a goto). If you're going to do it a couple of billion times and the function is a time pig, I can see sacrificing readability to efficiency. Of course, the logic stated in the previous paragraph would not hold if (a) you write perfect code the first time and will never need to look at it again; (b) only persons with your level of brilliance and your programming experience ever look at your code. Since your affiliaton is MIT, I must presume that both conditions hold.
jik@athena.mit.edu (Jonathan I. Kamens) (05/08/89)
In article <24127@agate.BERKELEY.EDU> ked@garnet.berkeley.edu (Earl H. Kinmonth) writes: >Please run this one past me again. Since I'm an historian and not a >programmer my mind must work differently. If you are doing it only once >and only micro-seconds are involved, the clearest form should prevail >(a subroutine rather than a goto). If you're going to do it a couple of >billion times and the function is a time pig, I can see sacrificing >readability to efficiency. You're right, my answer was not well thought out. >Of course, the logic stated in the previous paragraph would not hold if >(a) you write perfect code the first time and will never need to look >at it again; (b) only persons with your level of brilliance and your >programming experience ever look at your code. > >Since your affiliaton is MIT, I must presume that both conditions hold. Even if my posting was wrong, at least it was not obnoxious. It seems to me that this comment is, IMHO. Jonathan Kamens USnail: MIT Project Athena 410 Memorial Drive, No. 223F jik@Athena.MIT.EDU Cambridge, MA 02139-4318 Office: 617-253-4261 Home: 617-225-8218
kers@otter.hpl.hp.com (Chris Dollin) (05/08/89)
lishka@uwslh.UUCP (a.k.a. Fish-Guts) (also Christopher Lishka) said: [stuff omitted] | So there are the comments, "straight from the horses' mouthes!" | There are times (especially when writing recursive-descent compilers) | when the use of one _goto_ or longjmp() can save many, many additional | tests. Note that the setjmp()/longjmp() functions are just a | _goto_/label equivalent that can jump across functions (by unwinding | the stack). _Goto_ does have its place! Funny, I never found it necessary or convenient to use goto's in a RD parser. Error recovery can be done very-nicely-thank-you by passing the set of permitted symbols to the next-token routine - as both Henry Specer and I have avowed in (I think) comp.compilers recently. Regards, Kers. "If anything anyone lacks, they'll find it all ready in stacks."
rjd@occrsh.ATT.COM (Randy_Davis) (05/08/89)
In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: [...] |How many times have you seen this kind of code? | | printf ("Enter your sex: "); | while (sex != "m" && sex != "f") { | gets (sex); | if (sex != "m" && sex != "f") | printf ("<m> or <f> only: "); | } | |Why make the test twice? Huh? Huh? Answer me that, all you obsessed |anti-GOTO campaigners. The *natural* way to express the above is: | | printf ("Enter your sex: "); |LABEL: gets (sex); | if (sex != "m" && sex != "f") { | printf ("<m> or <f> only: "); | GOTO LABEL; | } | |Better examples abound, but in time honoured way, elude me now that I [...] This is the natural way for *me* to express the above example: printf ("Enter your sex: "); gets(sex); while(sex[0] != 'm' && sex[0] != 'f') { printf ("<m> or <f> only: "); gets(sex); } Now, admittedly, this is just the answer to *one* example *AND* it duplicates one instruction (the gets) and thus makes the program incrementally larger. YET, I have yet to see a GOTO program that could not have easily been written without it.... Not neccessarily faster or more efficiently mind you - *I* am not a "rabid anti-GOTOer", yet they rarely add to the readability of the program, not that that is always an important attribute. It just seems to me to be the mark of a lazy programmer that doesn't take the time to think of a way around the GOTO. If he does know the way around it and does it for a more efficient or more compact program, though - that's another story. Randy Davis UUCP: ...(att!)ocrjd!randy ...(att!)occrsh!rjd
hollombe@ttidca.TTI.COM (The Polymath) (05/09/89)
In article <2854@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: }... Actually, I feel that 'break' should usually be replaced by }an explicit goto (heresy!). Why? Because the place the break goes to }isn't explicit; you have to start matching up loops. ... Where the break goes is _very_ specific. It gets you out of the innermost containing loop (or switch). Where a goto goes is _anywhere_ it damn well wants to. I'd much rather match up a few braces (which, in _my_ coding standard, are aligned vertically on the page) than search through thousands of lines of code for a goto label. Not to mention finding such a label in the middle of a program and wondering how many goto statements go to it and where they are. -- The Polymath (aka: Jerry Hollombe, hollombe@ttidca.tti.com) Illegitimati Nil Citicorp(+)TTI Carborundum 3100 Ocean Park Blvd. (213) 452-9191, x2483 Santa Monica, CA 90405 {csun|philabs|psivax}!ttidca!hollombe
welty@algol.steinmetz (richard welty) (05/09/89)
the above set of keywords (who supplied these, anyway?) exactly sums up my own feelings on this topic ... In article <1166@mcrware.UUCP> jejones@mcrware.UUCP (James Jones) writes: >Let's all go read or reread Knuth, "Structured programming with goto >statements" (*Computing Surveys*, December 1974), so we can stop flogging >this dead horse, OK? It hasn't *quite* been 25 years since Dijkstra's >famous letter, but it's close. actually, i think that everyone ought to go back and look at Dijkstra's letter (geez, it's been 9 years since i read it) and at some of the surrounding debate at the time ... as i recall, Dijkstra was offering the observation that as an experiment he and some collegues had started a systematic effort to clarify a large algol 60 code, and noticed that as the number of goto's declined, the number of bugs went down. little did he know what a monster he had created ... at this point in time, after some 16 years of programming, the principle observations i have to offer is that if you are `forced' to use a goto, then somebody (either you, or your manglement, or that guy you inherited the code from who got fired two weeks before you started your job) probably made a bad decision. there are occasions for gotos, but they almost never arise in well-designed and well-implemented systems. also, goto is NEVER a good substitute for a well-designed and well-integrated exception-handling system. note that i am excluding `structured programming using gotos' as described in Knuth's article; in pre-fortran 77 days when i coded in fortran i generally coded according to Knuth's methods once i had learned about them. as for basic, which started all of this flamage, my personal feeling is that all basic programmers should be taken out and shot, in order to put them out of their misery. finally, i offer my own solution to the `sex' problem, in Common Lisp (all this C is doing bad things for my digestion.) Oh, yes -- it also uses the MIT Loop macro (i can see you lisp purists wincing out there.) this is, i believe, the original (i pinched this from Jerry Hollombe's article, and am assuming it it the original.) } printf ("Enter your sex: "); } while (sex != "m" && sex != "f") { } gets (sex); } if (sex != "m" && sex != "f") } printf ("<m> or <f> only: "); } } the above is a truly ugly piece of code, and i don't believe that it really works, although i haven't written more than 30 lines of C in the past 3 years. the following was tested in lucid cl version 3.0.2, by the way, and works perfectly. (defun get-sex (&optional (stream *terminal-io*)) "queries for user's sex on stream. returns nil if premature eof encountered premature ejaculation condition not handled" (write-line "Enter your sex (m or f)" stream) (loop for sex = (read-line stream nil nil) when (null sex) return nil ; eof error when (or (string-equal sex "m") (string-equal sex "f")) return sex do (write-line "m or f only please"))) it would look uglier without the loop macro; something like the following version which uses the simple common lisp loop (note that (return <value>) in common lisp is roughly comparable to C's break statement, except that being function-oriented, lisp returns a value): (defun get-sex (&optional (stream *terminal-io*)) "queries for user's sex on stream. returns nil if premature eof encountered premature ejaculation condition not handled" (write-line "Enter your sex (m or f)" stream) (let (sex) (loop (setq sex (read-line stream nil nil)) (when (null sex) (return nil)) (when (or (string-equal sex "m") (string-equal sex "f")) (return sex)) (write-line "m or f only please")))) enough of this nonsense, richard -- richard welty welty@algol.crd.ge.com 518-387-6346, GE R&D, K1-5C39, Niskayuna, New York ``Quotes and commas and backquotes, oh my''
jlg@lanl.gov (Jim Giles) (05/09/89)
From article <905@twwells.uucp>, by bill@twwells.uucp (T. William Wells): > In article <13113@lanl.gov> jlg@lanl.gov (Jim Giles) writes: > : if (cond1) { > : [...A...] /* lots of code */ > : goto LABEL;} > : else if (cond2) { > : LABEL: [...B...] /* lots more code */ > : } > [...] > : Solution 2) imposes a code space penalty > : as well as making code maintenance difficult (you must always remember to > : update _both_ versions of 'B'). > > Only half true. Many (most?) optimizers will recognize that the two > code sequences are identical and put the branch where you would > expect. There's a limit to what an optimizer can do. Suppose the example were a long sequence of "else if"s and that SEVERAL distinct branches all ended with sequence B. Or, suppose the long sequence of "else if"s contain some branches that end with sequence B and others that end with C where B and C are disjoint. Duplicating the code can waste a _lot_ of space and really make maintenance a nightmare! > [...] > Be aware that a *single* goto in a function can cause many optimizers > to do nothing for the function. The reason for this is that many of > the better optimization techniques depend on the program having a > particular control structure and transforming an arbitrary program > into one that is acceptable is a hairy task. This is _REALLY_ irritating though. The example above obeys all the "rules" of a well structured control construct: it has only one entry; it has only one exit; it flows strictly from top to bottom of the page; etc.. There _IS_ a language feature that allows this to be done with an accepted "structured" mechanism. I hesitate to mention it though, since it is _much_ less readible than the version with GOTOs - it was an "event driven" mechanism devised by Zahn (C.T. Zahn. "A Control Statement for Natural Top-Down Structured Programming." Symp. on Programming Languages. Paris, 1974): begin quit on event1 if (cond1) { [...A...] /* lots of code */ raise event1;} else if (cond2) { raise event1; } then event1: [...B...] /* lots more code */ end In this case, the sequence between "begin" and "then" is executed once (or until a named event arises). If no even arises, the part between "then" and "end" is simply skipped. If a named event arises (they all must be listed on the "begin" line and each must have a handler in the "then" part) the corresponding event handler is executed and the program continues with whatever follows "end". I don't like this as well as I do GOTOs. In the Nemesis programming language, the words "begin" and "end" have no flow-control meaning. They are instead used, entirely, to allow local restrictions on scope. So: Begin ! exclamation point is comment marker Import all ! bring in all outside declarations If (cond1) then ![...A...] stands for lots of code Goto 1 Else if (cond2) then 1 continue ! label may only appear on a no-op statement ![...B...] stands for lots more code Endif End This limits the scope on the statement label '1' in such a way that it can't be jumped to from outside the begin-end block. IMHO this provides the correct level of control over how GOTO is used without unduely constraining the programmer or obscuring the program. Of course, Nemesis doesn't _require_ that you limit the visability of labels this way, nor does it restrict _where_ a label may occur. But, there's only so much hand-holding a language can provide.
john@frog.UUCP (John Woods) (05/09/89)
In article <1191@aplcen.apl.jhu.edu>, arrom@aplcen.apl.jhu.edu (Ken Arromdee) writes: > >do { < > fprintf(stdout, "Enter your sex (<m> or <f> only): "); > > fflush(stdout); < > fgets(stdin, sex, 2); > > fflush(stdin); < >} while ((*sex != 'm') && (*sex != 'f')); > < This is not analogous. > < The original example prints the "<m> or <f> only:" message only if the > input is not an "m" or "f". This supposeedly analogous program prints it < every time. > Exactly. That is why the second program is better. It encourages the desired response the first time around. That kind of software ENGINEERING goes against the grain of BASIC programming, however :-). If you really must have the original confusing prompt structure, fill in the blanks: printf(_); while (1) { gets(_); if (_) break; printf(_); } Voila! The loop-and-a-half. -- John Woods, Charles River Data Systems, Framingham MA, (508) 626-1101 ...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu Fellow cranks!! ...I'm not ALONE!!
christer@rachel.cs.umu.se (Christer Ericson) (05/09/89)
I think all of you who have been discussing GOTO's should take a look at the March '87 issue of CACM and read Rubin's '"GOTO Considered Harmful" Considered Harmful' along with Dijkstra's reply in the August '87 issue and finally Rubin's reply to Dijkstra in the December issue. For those of you who don't have the time to look this issues up here is a small [very small] summary: Rubin states the following problem: "Let X be an N x N matrix of integers. Write a program that will print the number of the first all-zero row of X, if any." Along with this he presents the following program with a goto [also two other programs w/o gotos that are disgusting to look at]: [BTW, I reindented the program a bit] for i:=1 to n do begin for j:=1 to n do if x[i,j]<>0 then goto reject; writeln('The first all-zero row is ',i); break; reject: end; In his reply Dijkstra complained about silly things like that Rubin used lowercase letters [x,n] in the program and uppercase letters [X,N] in the problem specification... He also presented his solution to the problem using a very Dijkstaescue notation [which makes it difficult to retype it here, so I won't try that.] Anyway, in his final letter Rubin expresses his disappointment over Dijkstras reply [which he had all reasons in the world to do!] and also this Pascal version of Dijkstras program: c:=true; i:=0; while c and (i<>n) do begin d:=true; j:=0; while d and (j<>n) do begin d:=x[i,j]=0; j:=j+1; end; c:=not d; i:=i+1; end; if c then skip else print (i-1); I think that the above code says it all... I would like to know if ANYONE think Dijkstras program is easier to read [which IS the question, right?] than Rubins? Go read the original articles NOW! /Christer | Christer Ericson Internet: christer@cs.umu.se | | Department of Computer Science, University of Umea, S-90187 UMEA, Sweden | | "I bully sheep. I say GOTOs are necessary!" :-) |
les@chinet.chi.il.us (Leslie Mikesell) (05/09/89)
In article <4383@ttidca.TTI.COM> hollombe@ttidcb.tti.com (The Polymath) writes: >Where the break goes is _very_ specific. It gets you out of the innermost >containing loop (or switch). Where a goto goes is _anywhere_ it damn well >wants to. I'd much rather match up a few braces (which, in _my_ coding >standard, are aligned vertically on the page) than search through thousands >of lines of code for a goto label. Not to mention finding such a label in >the middle of a program and wondering how many goto statements go to it >and where they are. Who uses paper anymore? Any editor worth loading can find all the references to a label faster than you can determine if a "break" is inside of a switch or not (assuming you were bright enough to make the label a unique piece of text). I wish someone would re-think programming languages in the context of intelligent editors. I would really like to see "named" enclosing braces like this: if (foo) {:foo-cond while (bar < 2) {:bar-loop do_something(); bar++; }:bar-loop }:foo-cond where bar-loop and foo-cond are arbitrary and optional text that must match at the start and end. Ordinarily I don't like extra verbosity but sometimes I get the feeling I'm in a maze of twisty {}'s, that all look alike. This would also allow a reasonable diagnostic from lint or the compiler when a brace is misplaced. Can't we forget about the days of paper-tape and punch cards? Les Mikesell
jacka@hpcupt1.HP.COM (Jack C. Armstrong) (05/09/89)
In all of this GOTO/NOGOTO nonsense, no one seems to have mentioned just WHY gotos are so ugly - it's not the goto statement that causes readability problems - is the %&#!$! label! When reading source written by others (or myself, more than 5 minutes ago) the presense of a label tells me *somebody*, *somewhere* does a goto to this location. The question is - who? from where? [N.B. the break and return statements used in C have the same problem, with the added 'charm' of no explicit label. A goto by any other name.....] Cross-listing directories help, but how long do they stay accurate? In the interest of free speech, I hate to see gotos totally censored, and as an old Algol 60 hacker from the 60's I avoid them like the plague, but I'll still stand up for your right to use them judiciously, where needed, but *please* comment on its use!
hollombe@ttidca.TTI.COM (The Polymath) (05/10/89)
In article <1745@wasatch.utah.edu> cetron@wasatch.utah.edu (Edward J Cetron) writes: } This entire GOTO debate seems to be indicative of the quality of }programmers currently available today. To them, STRUCTURE is EVERYTHING. }They've even forgotten (or never learned WHY structured concepts are good). }But MOST IMPORTANTLY the forget that somewhere, somehow, a computer HAS to }execute these programs. Before I ever was taught about programming, I was }taught how the computers worked at the machine code level. If once only }considers the computer at the HLL level, no matter how good and optimizing }compiler you have, you can still write stuff that is damned inefficient. } } [ etc. in the above vein ] When I'm concerned about machine efficiency, I write in assembler. (I've written a _lot_ of assembler on some projects). In my current environment, I'm concerned about portability. There are always tradeoffs. -- The Polymath (aka: Jerry Hollombe, hollombe@ttidca.tti.com) Illegitimati Nil Citicorp(+)TTI Carborundum 3100 Ocean Park Blvd. (213) 452-9191, x2483 Santa Monica, CA 90405 {csun|philabs|psivax}!ttidca!hollombe
hollombe@ttidca.TTI.COM (The Polymath) (05/10/89)
In article <1383@cygnet.CYGNETSYSTEMS> mark@cygnet.UUCP (Mark Quattrocchi) writes: }In article <11136@bloom-beacon.MIT.EDU> jik@athena.mit.edu (Jonathan I. Kamens) writes: }>In article <1814@ubu.warwick.UUCP> mirk@uk.ac.warwick.cs (Mike Taylor) writes: }>>How many times have you seen this kind of code? }>> }>> printf ("Enter your sex: "); }>> while (sex != "m" && sex != "f") { }>> gets (sex); }>> if (sex != "m" && sex != "f") }>> printf ("<m> or <f> only: "); }>> } }> }>Indeed, this is a pretty bad example of where a goto would be useful, }>because you are simply illustrating what the purpose of the C do ... }>while construct is for: }> }>do { }> fprintf(stdout, "Enter your sex (<m> or <f> only): "); }> fflush(stdout); }> fgets(stdin, sex, 2); }> fflush(stdin); }>} while ((*sex != 'm') && (*sex != 'f')); }Speaking of jumping to conclusions, your code is not a one for one }equivalent of the original. Even though I agree with your interpretation, }you are cheating by combining the print statements together. Try again }only don't cheat. This isn't cheating. Both code fragments accomplish the same function -- getting the user's sex. The second fragment does it better on several counts. Not only is the code simpler, more efficient and easier to maintain, but it helps prevent the end user from making an avoidable error. Human factors is part of programming. -- The Polymath (aka: Jerry Hollombe, hollombe@ttidca.tti.com) Illegitimati Nil Citicorp(+)TTI Carborundum 3100 Ocean Park Blvd. (213) 452-9191, x2483 Santa Monica, CA 90405 {csun|philabs|psivax}!ttidca!hollombe
dts@quad.uucp (David T. Sandberg) (05/10/89)
In article <852@umecs.cs.umu.se> christer@rachel.UUCP (Christer Ericson) writes: LOCATION: | I think all of you who have been discussing GOTO's should take a look at the | March '87 issue of CACM and read Rubin's '"GOTO Considered Harmful" Considered | Harmful' along with Dijkstra's reply in the August '87 issue and finally | Rubin's reply to Dijkstra in the December issue. | | [code deleted to appease inews] | | I think that the above code says it all... I would like to know if ANYONE | think Dijkstras program is easier to read [which IS the question, right?] | than Rubins? Not as written, but with a few alterations (like using more descriptive variable names, an if statement instead of the logical assignment in the inner loop, etc.) I would prefer the non-GOTO style. Really. ;') Whether or not GOTOs are acceptable is largely a matter of the kind of code you (and your coworkers!) are used to reading. I haven't used a GOTO for a very long time, and I actually had to take a second look at the GOTO version to understand how it worked. But even with the arbitrarily convuluted elements of Dijkstra's version, I knew how it worked at first glance. One thing the code samples you presented do *not* prove is the acceptability of GOTO code with jumps longer than a few lines. Sure, it's easy to see where a GOTO is leading when both the GOTO and it's target location appear right there on your 24-line screen, but when you are working on code of any significant size and complexity, the issue of knowing where the GOTO points to rears it's fugly head. For an example, pretend this article is a code segment. Now, quick, tell me where we're going... ;') goto LOCATION; -- char *david_sandberg() { return ( dts@quad.uucp || uunet!rosevax!sialis!quad!dts ); }
jik@athena.mit.edu (Jonathan I. Kamens) (05/10/89)
In article <852@umecs.cs.umu.se> christer@rachel.UUCP (Christer Ericson) writes: >I think that the above code says it all... I would like to know if ANYONE >think Dijkstras program is easier to read [which IS the question, right?] >than Rubins? First of all, whether the program is easier to read or not is only *part* of the question. Some of the other factors involved are: * In a large program using goto's (although it is obviously not a problem in the case of a very small piece of code like the examples that have been provided), it tends to be more hazardous to make changes and corrections to the code without screwing something up. * Many compilers (as has already been pointed out) have trouble optimizing code that has goto's in it. They therefore don't try to optimize, which results in less efficient programs. >Go read the original articles NOW! Personally, I think it is quite possible for someone to conduct an intelligent discussion about goto's without having read the sources to which you refer, although they might help. Anyone who has programmed both in Applesoft BASIC and C, for example, might have a lot to say about the relative merits of goto's :-) Jonathan Kamens USnail: MIT Project Athena 410 Memorial Drive, No. 223F jik@Athena.MIT.EDU Cambridge, MA 02139-4318 Office: 617-253-4261 Home: 617-225-8218
phco@ecsvax.UUCP (John Miller) (05/10/89)
>where we're going... ;') > > goto LOCATION; > Here's another code segment (label only): LOCATION: Now, quick, tell me where we're coming from! In many cases the mere existence of a label can be more confusing than the presence of a "goto" because it implies an unknown number of jumps from multiple unknown locations. If you have to have a label in your code, put a comment with it to explain why it's there, e.g., LOCATION: /* here begins code for handling abnormal termination (i.e., goto) of function blah() or function huh() */ -- John Miller (ecsvax!phco) Dept. of Pharmacology, Univ. of N.C.-Chapel Hill CB#7365 1026A FLOB Chapel Hill, NC 27599 (919) 966-6966
geoff@cs.warwick.ac.uk (Geoff Rimmer) (05/10/89)
Here is my solution. Which does the same as that of the original poster, and in addition: (a) it checks the buffer overflowing; (b) it checks for EOF (c) it is correct C code ----------------------------------------------------------------------------- #include <stdio.h> main() { char str[4]; printf("Enter your sex: "); do { fflush(stdin); if (!fgets(str,3,stdin)) exit(1); } while (*str!="m" && *str!="f") ? printf("m or f only: "):0); printf("sex is %c\n",*str); } ----------------------------------------------------------------------------- In the original poster's FOLLOWUP article, he writes: > Equally invalid, (though correct) are the solutions posted by some > people of the form: > > printf (message1); > while (gets (sex), (*sex != 'm' && *sex != 'f')) > printf (message2); > > This involves a C-specific construct (the comma operator that allows > you to do lots of stuff between checks), which is one of the neat > things about C, but does nothing to remove the difficulty of > expressing some logic-routes in generic structured contructs. If you don't like these "neat tricks" as you call them, you are quite free to go choose another language to program in. However, the implication of the original posting was that you were referring to C, and that is why everyone has given answers in C. The operators like "," and "?:" are very useful, and you shouldn't complain at people for using them because they are "C-Specific". If you've got features, use em! Geoff - "You can't beat the feeling" /---------------------------------------------------------------\ | GEOFF RIMMER - Friend of COCA COLA CLASSIC | | email : geoff@uk.ac.warwick.cs | | address : Computer Science Dept, Warwick University, | | Coventry, England. | | PHONE : +44 203 692320 (9 lines) | | FAX : +44 865 726753 | \---------------------------------------------------------------/
joe@logi-dc.UUCP (Joe Dzikiewicz) (05/11/89)
Talk about vampire debates! Folks have been having flame wars on the GOTO issue since before the net was born. Can't we put a stake in the heart of this issue and agree to disagree? yeesh, Joe Dzikiewicz
bill@twwells.uucp (T. William Wells) (05/11/89)
In article <852@umecs.cs.umu.se> christer@rachel.UUCP (Christer Ericson) writes: : Rubin states the following problem: : "Let X be an N x N matrix of integers. Write a program that will print the : number of the first all-zero row of X, if any." : : Along with this he presents the following program with a goto [also two other : programs w/o gotos that are disgusting to look at]: : : [BTW, I reindented the program a bit] : : for i:=1 to n do begin : for j:=1 to n do : if x[i,j]<>0 then goto reject; : writeln('The first all-zero row is ',i); : break; : reject: : end; Why don't I use Pascal anymore? Because C says it much better. (NB: array origins have been made 0 and no declarations are shown.) for (i = 0; i < N; ++i) { for (j = 0; X[i][j] == 0; ) { if (++j == N) { printf("The first all-zero row is %d\n", i); return; } } } And if one insists on not putting this into its own function (making the return improper): for (i = 0; i < N; ++i) { for (j = 0; X[i][j] == 0; ) { if (++j == N) { printf("The first all-zero row is %d\n", i); break; } } if (j == N) { break; } } One could, of course, turn the first break into a goto, but eliminating the possible cost of the j == n test isn't worth the loss of clarity. --- Bill { uunet | novavax } !twwells!bill
jlg@lanl.gov (Jim Giles) (05/11/89)
In article <852@umecs.cs.umu.se> christer@rachel.UUCP (Christer Ericson) writes: > [...] > One thing the code samples you presented do *not* prove is > the acceptability of GOTO code with jumps longer than a few > lines. Sure, it's easy to see where a GOTO is leading when > both the GOTO and it's target location appear right there on > your 24-line screen, but when you are working on code of any > significant size and complexity, the issue of knowing where > the GOTO points to rears it's fugly head. For an example, > pretend this article is a code segment. Now, quick, tell me > where we're going... ;') Unfortunately, the _SAME_ problem exists when you introduce a boolean to replace the GOTO. If you can't see the use of the flag right away, then its presence in your code is just as mysterious as the GOTO is (ie. where is this niggly little flag variable used?). Often you find that the flag is used _several_ places - that's certainly not the case with GOTOs. When you find the place where a flag is used you have no assurance that you've found the _only_ use. The 'fan-out' of the GOTO is one, the 'fan-out' of the boolean is unbounded. > Here's another code segment (label only): > > LOCATION: > > Now, quick, tell me where we're coming from! In many cases the mere > existence of a label can be more confusing than the presence of a "goto" > because it implies an unknown number of jumps from multiple unknown > locations. Ok, now try this example: if (aflag) then [...] Now, quick, tell me where aflag was set! In many cases the mere existence of a flag can be more confusing that the presence of a GOTO because it implies an unknown number of paths through the preceding code may have set the flag. 8') Now, in truth, the 'fan-in' of a boolean and a label are exactly of the same complexity. Selecting mnemonic identifiers for either will increase readibility. So will the presence of appropriate comments. _BUT_, the real _MEANING_ of a flag is the union of all the conditions which could cause the flag to be set - the real _MEANING_ of a label is the union of all the conditions which could cause a jump to it (or a flow to it). Neither is intrinsically simpler than the other. Which _looks_ best to _you_ is a subjective decision. To be sure, GOTOs can be abused to produce spaghetti code. Unfortunately, flags and/or conditions can implement the _same_ spaghetti! I have seen well "structured" (no GOTOs) code in which the flow of control bounces all over everywhere (lots of conditions and flags, lots of IFs and CASEs, all inside a loop). By the way, the POINTER in data structuring is isomorphic to the GOTO in flow control. The POINTER can be abused to produce spaghetti data structures. Any anti-GOTO fanatics out there want to ban the POINTER too?
bill@twwells.uucp (T. William Wells) (05/11/89)
In article <13301@lanl.gov> jlg@lanl.gov (Jim Giles) writes: : From article <905@twwells.uucp>, by bill@twwells.uucp (T. William Wells): : > In article <13113@lanl.gov> jlg@lanl.gov (Jim Giles) writes: : > : if (cond1) { : > : [...A...] /* lots of code */ : > : goto LABEL;} : > : else if (cond2) { : > : LABEL: [...B...] /* lots more code */ : > : } : > [...] : > : Solution 2) imposes a code space penalty : > : as well as making code maintenance difficult (you must always remember to : > : update _both_ versions of 'B'). : > : > Only half true. Many (most?) optimizers will recognize that the two : > code sequences are identical and put the branch where you would : > expect. : : There's a limit to what an optimizer can do. Suppose the example were : a long sequence of "else if"s and that SEVERAL distinct branches all ended : with sequence B. Or, suppose the long sequence of "else if"s contain : some branches that end with sequence B and others that end with C where : B and C are disjoint. Duplicating the code can waste a _lot_ of space : and really make maintenance a nightmare! What these optimizers do is to start from a point which several code sequences end at and work backwards on all branches, munching instructions so long as they are identical. So those are not really problems. My own experience is that, while it is theoretically possible to waste a lot space in this way, in practice it doesn't happen. The place where I've been most tempted to use a goto is, however, very similar; had I succumbed, I'd have written code like: switch (n) { case 1: A; goto label; case 2: B; label: C; } So far, I've always found an acceptable way to avoid doing this. : > Be aware that a *single* goto in a function can cause many optimizers : > to do nothing for the function. The reason for this is that many of : > the better optimization techniques depend on the program having a : > particular control structure and transforming an arbitrary program : > into one that is acceptable is a hairy task. : : This is _REALLY_ irritating though. The example above obeys all the : "rules" of a well structured control construct: it has only one entry; Oh, I agree. That doesn't mean that these optimizers are smart enough to recognize that it is so. The problem is that the code to do this generally is hairy; however, writing code that handles enough of the special cases is a real chore and there is no guarantee that one really has done enough. Or so the reasoning goes. --- Bill { uunet | novavax } !twwells!bill
jik@athena.mit.edu (Jonathan I. Kamens) (05/12/89)
In article <1860@ubu.warwick.UUCP> geoff@cs.warwick.ac.uk (Geoff Rimmer) writes: >Here is my solution. Which does the same as that of the original >poster, and in addition: > >(a) it checks the buffer overflowing; >(b) it checks for EOF >(c) it is correct C code Actually, it is not correct C code for six reasons. In fact, it won't even compile. It's not very intelligent in an argument like this to be all high-and-mighty and post a code fragment that you claim is "correct C code" when it won't even compile. Here's the code you posted: >#include <stdio.h> > >main() >{ > char str[4]; > printf("Enter your sex: "); > do > { > fflush(stdin); > if (!fgets(str,3,stdin)) exit(1); > } while (*str!="m" && *str!="f") ? printf("m or f only: "):0); > printf("sex is %c\n",*str); >} 1. You aren't flushing stdout after printing the prompt, and the prompt does not end in a newline, so in many operating systems the prompt will not be printed. 2. You flush stdin, but, to quote from the man page: Fflush causes any buffered data for the named output stream to be written to that file. The stream remains open. In other words, fflush is not defined for input files, and stdin is input-only. 3. You assume that printf will return a non-zero value. Now, I don't know about your implementation of printf, but mine (BSD 4.3) doesn't spec what printf returns, and I don't think that most implementations ahve such a specification (although I believe that ANSI says printf should return the number of characters it's printed). In fact, I just compiled your program (with the two bugs below fixed, since it won't compile otherwise), and our IBM RT library seems to return 0 after a successful printf, so your code loses. 4. You're missing a parenthesis at the beginning of your while boolean expression. 5. You're comparing the value of a char to the value of a string pointer in your boolean expression. It should be (*str!='m' && *str!='f') rather than what you have. 6. It doesn't print an error message if the fgets fails. Now, granted, this isn't really "incorrect C," but rather "incorrect programming," but it should be pointed out nevertheless. Oh, and one more thing: what the hell good is a program that does nothing but get somebody's sex and print it? :-) Jonathan Kamens USnail: MIT Project Athena 410 Memorial Drive, No. 223F jik@Athena.MIT.EDU Cambridge, MA 02139-4318 Office: 617-253-4261 Home: 617-225-8218
dts@quad.uucp (David T. Sandberg) (05/12/89)
In article <13424@lanl.gov> jlg@lanl.gov (Jim Giles) writes: |In article <852@umecs.cs.umu.se> christer@rachel.UUCP (Christer Ericson) writes: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Wrong person. The first set of comments you quoted are mine. |> ...... Sure, it's easy to see where a GOTO is leading when |> both the GOTO and it's target location appear right there on |> your 24-line screen, but when you are working on code of any |> significant size and complexity, the issue of knowing where |> the GOTO points to rears it's fugly head. For an example, |> pretend this article is a code segment. Now, quick, tell me |> where we're going... ;') | |Unfortunately, the _SAME_ problem exists when you introduce a boolean |to replace the GOTO. If you can't see the use of the flag right away, |then its presence in your code is just as mysterious as the GOTO is |(ie. where is this niggly little flag variable used?). Often you find |that the flag is used _several_ places - that's certainly not the case |with GOTOs. When you find the place where a flag is used you have no |assurance that you've found the _only_ use. The 'fan-out' of the |GOTO is one, the 'fan-out' of the boolean is unbounded. The "fan out" of a GOTO may be one, but the "fan in" of that GOTO's label is unbounded (any number of GOTOs can use it as an entry point). Also, GOTOs can jump to any part of the program which they like: different functions, different modules, etc. On the other hand, a flag is almost always set within the function of it's usage (or at least passed in as a parameter). You could counter that using a global flag would create the same kind of problem as GOTOs are subject to, but anyone who would use a global flag for controlling a conditional expression deserves what they get. |> Here's another code segment (label only): |> |> LOCATION: |> |> Now, quick, tell me where we're coming from! This was Christor Ericson's followup comment to my original article, and it was well said. I wish I had said as much my first time around. |Now, in truth, the 'fan-in' of a boolean and a label are exactly |of the same complexity. Selecting mnemonic identifiers for either |will increase readibility. So will the presence of appropriate |comments. No, the "fan-in" of a *global* boolean and a label are exactly of the same complexity. A local flag (the common & preferred method) has a much more restricted scope. You are right, though, that meaningful identifiers and comments help in both cases. |Which _looks_ best to _you_ is a subjective decision. Sounds about right, but your original contention was that, in the code fragments you presented, the GOTO version should look better to all onlookers. I hope I've convinced you that I sincerely would rather work with the structured version. |To be sure, GOTOs can be abused to produce spaghetti code. Unfortunately, |flags and/or conditions can implement the _same_ spaghetti! I have |seen well "structured" (no GOTOs) code in which the flow of control |bounces all over everywhere (lots of conditions and flags, lots of |IFs and CASEs, all inside a loop). I'll give you that. Any structure can be used for good or bad code. My observation is that the GOTO leads more directly to bad code than to good. Now, I wouldn't go into convulsions if confronted by the short little GOTO hops you presented earlier, but if I was asked to write software to accomplish those tasks, I would certainly find it more natural to produce code resembling the structured example. |By the way, the POINTER in data structuring is isomorphic to the GOTO |in flow control. The POINTER can be abused to produce spaghetti data |structures. Any anti-GOTO fanatics out there want to ban the POINTER |too? This is an interesting point which I'll have to consider. (Not that I think it likely that I'll start using GOTOs or give up pointers entirely, mind you... ;') -- char *david_sandberg() { return ( dts@quad.uucp || uunet!rosevax!sialis!quad!dts ); }
bill@twwells.uucp (T. William Wells) (05/12/89)
In article <6540009@hpcupt1.HP.COM> jacka@hpcupt1.HP.COM (Jack C. Armstrong) writes:
: In all of this GOTO/NOGOTO nonsense, no one seems to have mentioned just
: WHY gotos are so ugly - it's not the goto statement that causes readability
: problems - is the %&#!$! label! When reading source written by others (or
: myself, more than 5 minutes ago) the presense of a label tells me *somebody*,
: *somewhere* does a goto to this location. The question is - who? from where?
This is all perfectly correct and is implicit in "making the control
structures apparent", the point of structured programming.
: [N.B. the break and return statements used in C have the same problem, with
: the added 'charm' of no explicit label. A goto by any other name.....]
But this is a non sequiter. *All* control structures are "goto[s] by
any other name". Break and return are very easy to deal with. Return
always leaves the current function (you *do* know what that is,
right?). Break and continue always leave the innermost loop or
switch; provided that you've indented the code correctly, the place
the break goes to is immediately obvious.
: Cross-listing directories help, but how long do they stay accurate? In the
: interest of free speech, I hate to see gotos totally censored, and as an old
: Algol 60 hacker from the 60's I avoid them like the plague, but I'll still
: stand up for your right to use them judiciously, where needed, but *please*
: comment on its use!
The coding standard where I work (written by myself) requires this;
moreover, when efficiency is the claimed reason, the comment is
required to have the timing statistics to prove it.
---
Bill { uunet | novavax } !twwells!bill
jlg@lanl.gov (Jim Giles) (05/12/89)
From article <137@quad.uucp>, by dts@quad.uucp (David T. Sandberg): > [...] > The "fan out" of a GOTO may be one, but the "fan in" of that GOTO's > label is unbounded (any number of GOTOs can use it as an entry point). Which is _exactly_ what I said in my posting. I also pointed out that the "fan-in" of booleans is _also_ unbounded. > Also, GOTOs can jump to any part of the program which they like: > different functions, different modules, etc. [...] Maybe they can in C. But in MOST programming languages, a statement label is _purely_ local. Not even Fortran allows GOTO to refer to a non-local label (even with assigned GOTO this is illegal, but _some_ old implementations allowed it). > [...] On the other hand, > a flag is almost always set within the function of it's usage (or > at least passed in as a parameter). [...] But, unlike GOTOs, a boolean _CAN_ be be passed around as a global! The language (any language) will permit the occurance. This is _not_ true of labels (which, as I've said before, are _required_ to be local by most programming languages). > [...] You could counter that using > a global flag would create the same kind of problem as GOTOs are > subject to, but anyone who would use a global flag for controlling > a conditional expression deserves what they get. Yes, but you don't have to evade the rules of the language to misuse booleans in this way. Anyone who uses GOTO for inter-procedural transfer deserves what they get too! > |Now, in truth, the 'fan-in' of a boolean and a label are exactly > |of the same complexity. Selecting mnemonic identifiers for either > |will increase readibility. So will the presence of appropriate > |comments. > > No, the "fan-in" of a *global* boolean and a label are exactly of the > same complexity. A local flag (the common & preferred method) has a > much more restricted scope. Repeatedly saying this doesn't make it true. A label has exactly the _SAME_ scope as a local variable. A flag _CAN_ be given global scope. A label _CAN'T_ be given global scope (look it up - Pascal, Modula, Ada, ALGOL, not even Fortran). > [...] I hope I've convinced you that I sincerely would rather > work with the structured version. So would I. BUT, since _both_ our versions were structured, the debate seems to be bogged down on whether or not the "structured" version is best. (Definitions - structured: code developed by stepwise refinement using (ultimately) whatever low-level programming tools that are available. "structured": eliminating GOTOs from code, even where the GOTO is the most efficient method and is _AS_ readible and the proposed alternative.)
gateley@m2.csc.ti.com (John Gateley) (05/12/89)
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. John gateley@tilde.csc.ti.com
ked@garnet.berkeley.edu (Earl H. Kinmonth) (05/12/89)
>(Definitions - structured: code developed by stepwise refinement using >(ultimately) whatever low-level programming tools that are available. >"structured": eliminating GOTOs from code, even where the GOTO is the >most efficient method and is _AS_ readible and the proposed alternative.) As an historian, it is interesting to watch people in an allegedly hard and objective "science" make statements that are essentially ideological. Presumably even someone who is only computer literate can recognize the definitions of "structured" given here as essentially ideological. In a field where benchmarks are a generally accepted practice, it would seem possible to test goto(s). I would propose something like giving n versions of the code with goto(s) and n versions without to n programmers n months (or years) after the code was written. measure how many hours/days/weeks/months it takes on average to figure out what the hell is going on. The code with the lowest score wins. A further refinement might calculate ratios of person hours to understand the code / microseconds to excute the code. This would be, of course, a function of n different optimization techniques by the compiler which will change || wreck havoc with what you have written. If you don't like being flamed by an historian, take comfort in the fact that as a computer specialist your life time earnings stream will be substantially greater. Take comfort in that fact, and cut the shit. Earl H. Kinmonth a decade of C programming, and I've yet to use a goto since I gave up FORTRAN for Lent. History Department University of California, Davis Davis, California 95616 916-752-1636 (2300-0800 PDT for FAX) 916-752-0776 (secretary) ucbvax!ucdavis!ucdked!cck (email) cc-dnet.ucdavis.edu [128.120.2.251] (request ucdked, login as guest)
gorpong@telxon.UUCP (Gordon C. Galligher) (05/12/89)
In article <1745@wasatch.utah.edu> cetron@wasatch.utah.edu (Edward J Cetron) writes: > This entire GOTO debate seems to be indicative of the quality of >programmers currently available today. To them, STRUCTURE is EVERYTHING. >They've even forgotten (or never learned WHY structured concepts are good). >But MOST IMPORTANTLY the forget that somewhere, somehow, a computer HAS to >execute these programs. [...deleted Edward's personal history...] >I would >rather have a clearly written program (structured or not) which accomplishes >what the PROGRAM is intended to do, without excess baggage and }'s JUST to So you really don't care if anyone else can read this code to manage it? Believe it or not, but 80% of all code is in the maintenance stage (that's when it is either being modified to add new features, fix bugs, whatever), and if it was written to do just ONE task, who cares about how it looks, but it does the job, then you might as well advocate just throwing the program out and rewrite it to do the new tasks because it would be faster to do that than to try to read the code that the person wrote. The whole thing about writing re-usable code is to make it READ well. That's why most people are going to higher level languages for most things (I agree that for speed, assembly is probably the best choice, but if kept to a minimum) because higher level languages (if written "correctly") are easier to maintain. (The 'correctly' is an extremely subjective word and by that I mean written with the knowledge that you may not live forever and someone, someday will have to try to figure out what your code does! > Maybe that's why I only hire hardware oriented people. You can teach >a h/w person to program, but most s/w types are confused by hardware. I'm not going to TOUCH this!! :-). > Sorry for the flame, I'm just tired of interviewing smug new CS >students who know nothing about reality and using the right tools for the >job. They make great followers, but we desparately need thinkers and leaders. Have you ever thought about trying to HELP these "smug new CS students" by giving them some of your ideas, or are you too tied up trying to rewrite soft- ware you want to reuse? :-) -- Gordon. -- Gordon C. Galligher <|> ...!uunet!telxon!gorpong <|> gorpong@teleng.uucp.uu.net Telxon Corporation <|> "Captain, I hardly believe that insults are within your Akron, Ohio, 44313 <|> prerogative as my commanding officer" - Spock (216) 867-3700 (3512)<|> (City on the Edge of Forever (Starring Joan Collins))
gorpong@telxon.UUCP (Gordon C. Galligher) (05/13/89)
In article <13507@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >From article <137@quad.uucp>, by dts@quad.uucp (David T. Sandberg): >> [...] >> Also, GOTOs can jump to any part of the program which they like: >> different functions, different modules, etc. [...] > >Maybe they can in C. But in MOST programming languages, a statement >label is _purely_ local. Not even Fortran allows GOTO to refer to a No they can't. In C a goto can only be used within a function declaration. Some C libraries do employ the setjmp/longjmp sequence, but that deals with actually restoring the stack to what it was when the setjmp() was called, and it even puts the restriction that the function which called the setjmp() had still better be active when the longjmp() is called, or likely all h*&# will break loose. I know that comp.misc doesn't deal explicitly with C code (as someone deftly mentioned earlier by posting LISP source), but I also don't want someone who doesn't know C that well reading "Maybe they can in C" when they can't :-). ....I now return you to your regularly scheduled flame fest.... -- Gordon. -- Gordon C. Galligher <|> ...!uunet!telxon!gorpong <|> gorpong@teleng.uucp.uu.net Telxon Corporation <|> "Captain, I hardly believe that insults are within your Akron, Ohio, 44313 <|> prerogative as my commanding officer" - Spock (216) 867-3700 (3512)<|> (City on the Edge of Forever (Starring Joan Collins))
dts@quad.uucp (David T. Sandberg) (05/13/89)
In article <13507@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >From article <137@quad.uucp>, by dts@quad.uucp (David T. Sandberg): >> >> Also, GOTOs can jump to any part of the program which they like: >> different functions, different modules, etc. [...] > >Maybe they can in C. But in MOST programming languages, a statement >label is _purely_ local. Not even Fortran allows GOTO to refer to a >non-local label (even with assigned GOTO this is illegal, but _some_ >old implementations allowed it). Okay, here I need to withdraw my earlier comments. I have *never* used a goto in C (the language I was basing my comments on), and wasn't aware that the scope rules limit the visibility of a label to the current function. I have since checked this and learned the truth. By way of explanation, the only languages I have ever used GOTOs in are BASIC (shudder) and assembly, both of which have jumps without scope limits; hence my incorrect assumption. Sorry. >> ........... but anyone who would use a global flag for controlling >> a conditional expression deserves what they get. > >Yes, but you don't have to evade the rules of the language to misuse >booleans in this way. Anyone who uses GOTO for inter-procedural transfer >deserves what they get too! I agree. >> [...] I hope I've convinced you that I sincerely would rather >> work with the structured version. > >So would I. BUT, since _both_ our versions were structured, the debate >seems to be bogged down on whether or not the "structured" version is >best. Okay, let me rephrase that - given your definitions, I would prefer to work with the "structured" version. However, I still wouldn't call the version with a GOTO a structured version, for the reason that, in my understanding, one of the main rules of structured programming is that there are only three structures - sequential, iterative, and conditional. The GOTO can be used to create those constructs, but it can also be used, even within the scope of one function, to create structures not qualifying as one of those three constructs which define structured programming. >"structured": eliminating GOTOs from code, even where the GOTO is the >most efficient method and is _AS_ readible and the proposed alternative.) Whether it is _AS_ readable as the GOTO-less version is obviously not an absolute, since I for one did not find it so. -- char *david_sandberg() { return ( dts@quad.uucp || uunet!rosevax!sialis!quad!dts ); }
jlg@lanl.gov (Jim Giles) (05/13/89)
From article <140@quad.uucp>, by dts@quad.uucp (David T. Sandberg): > [...] > However, I still wouldn't call the version with a GOTO a structured > version, for the reason that, in my understanding, one of the main > rules of structured programming is that there are only three > structures - sequential, iterative, and conditional. [...] I read the definitive book: 'Structured Programming', by O.-J. Dahl, E.W. Dijkstra, and C.A.R. Hoare; when it first came out in 1972. This was after the famous 'GOTO Considered Harmful' letter and there is _one_ page in the book which discusses the need to use GOTOs with _care_. The rest of the book doesn't make recommendations on programming language flow control constructs - certainly it _never_ maintained that sequence, condition, and iteration are the _only_ way to write structured programs (in fact, there are examples in the book which use GOTOs). In any case, the original meaning of structured programming consisted of a model for program development (using stepwise refinement from an abstract specification of the task) plus a model for developing data structures (where GOTO's partner in crime - the lowly pointer - was _not_ even mentioned). It is too bad that the term "structured programming" has since become synonymous with GOTO evasion and nothing more. The principles in the book, while not followed by the vast majority of programmers ("structured" or not), are worth more than the debate about GOTOs has ever been.
stephen@ziebmef.uucp (Stephen M. Dunn) (05/14/89)
In article <2848@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: $In article <1814@ubu.warwick.UUCP> mirk@warwick.UUCP (Mike Taylor) writes: $ [ ... ] Listen, just 'cause Quiche-eater Wirth connected GOTOs with $ ^^^^^ $ lack of structure generally, doesn't mean either that (A) ALL use of $ GOTO is unstructured and obfuscatory, or that (B) ALL obfuscated code $ is due to use of GOTO -- so why is it that so many people seem to $ believe these myths? $It was Dijsktra [sp?]. Other than that, I perfectly agree! Dijkstra ... close but no carcinogenic cylinder. The statement above is quite correct IMHO. However, in a language like many dialects of BASIC which have no control structures other than FOR-NEXT, GOTO and GOSUB, it _can_ be next to impossible to write anything other than obfuscated spaghetti code. Note that this does not contradict either of the above points. Also, it is possible to write some very lousy code in languages which do not provide a GOTO (or, in those that do, by avoiding it), especially if they provide no means for prematurely terminating or repeating a loop other than a huge IF statement. And, of course, we all know it's possible to write very cryptic code in C, but that doesn't mean that C should be abolished (it just means that programmers should be taught not to write such code). Still, IMHO (for the second time) the use of GOTOs should be minimized whenever possible, since it generally does lead to harder-to- read programs which are unmaintainable by anyone other than the programmer (and often not even maintainable by him/her more than a couple of weeks later)! -- ------------------------------------------------------------------------------- ! Stephen M. Dunn stephen@ziebmef.UUCP ! DISCLAIMER: Who'd ever ! ! Take off to the Great White North eh, ya hosehead ! claim such dumb ideas? ! -------------------------------------------------------------------------------
cetron@wasatch.utah.edu (Edward J Cetron) (05/15/89)
In article <4396@ttidca.TTI.COM> hollombe@ttidcb.tti.com (The Polymath) writes: -In article cetron@wasatch.utah.edu (Edward J Cetron) writes: -} This entire GOTO debate seems to be indicative of the quality of -}programmers currently available today. To them, STRUCTURE is EVERYTHING. -When I'm concerned about machine efficiency, I write in assembler. (I've -written a _lot_ of assembler on some projects). In my current -environment, I'm concerned about portability. - -There are always tradeoffs. My point exactly - there are ALWAYS tradeoffs, but unless you have been trained/educated to realize that there are tradeoffs (and then to understand how to evaluate them), you have missed the boat. -ed cetron cetron@wasatch.utah.edu
cetron@wasatch.utah.edu (Edward J Cetron) (05/15/89)
In article <912@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes: >And if one insists on not putting this into its own function (making >the return improper): > > for (i = 0; i < N; ++i) { > for (j = 0; X[i][j] == 0; ) { > if (++j == N) { > printf("The first all-zero row is %d\n", i); > break; > } > } > if (j == N) { > break; > } > } > >One could, of course, turn the first break into a goto, but >eliminating the possible cost of the j == n test isn't worth the loss >of clarity. AHA! But what if it WAS a function? And what if it was some sort of very heavily used function? In THAT case wouldn't that fact that you saved that extra useless code be worth something? Maybe, maybe not. But if you understand your application, and you understand WHY structured programming, THEN, AND ONLY THEN, could you properly decide which is better. And that is my whole point - let's teach how to understand the problem and solve it correctly - not simply by-the-book. And to those who change the code to make it more user-friendly than the original - HURRAH. It is the function of the code, not its exact flow of control which is important. To those who bitched that the improved code didn't exactly translate to the original - you missed the whole damn point. -ed cetron
cetron@wasatch.utah.edu (Edward J Cetron) (05/15/89)
In article <46@telxon.UUCP> gorpong@telxon.UUCP (Gordon C. Galligher) writes: >In article <1745@wasatch.utah.edu> cetron@wasatch.utah.edu (Edward J Cetron) < writes: << This entire GOTO debate seems to be indicative of the quality of <<programmers currently available today. To them, STRUCTURE is EVERYTHING. <<They've even forgotten (or never learned WHY structured concepts are good). <<But MOST IMPORTANTLY the forget that somewhere, somehow, a computer HAS to <<execute these programs. <<I would <<rather have a clearly written program (structured or not) which accomplishes <<what the PROGRAM is intended to do, without excess baggage and }'s JUST to < <So you really don't care if anyone else can read this code to manage it? Didn't I say clearly written? Maintainable code can be written which DOES NOT have lots of {}'s with no purpose but to meet some example of structured programming style, not for clarity. <Believe it or not, but 80% of all code is in the maintenance stage ... <...the job, then you might as well advocate just throwing the program out and <rewrite it to do the new tasks because it would be faster to do that than to <try to read the code that the person wrote. I realize that maintainabilty is important, but the type who uses structured techniques for the sole purpose of using them is likely to also to write code which is poorly maintainable for other reasons. << Maybe that's why I only hire hardware oriented people. You can teach <<a h/w person to program, but most s/w types are confused by hardware. < <I'm not going to TOUCH this!! :-). Teaching s/w is an exercise is logic, organization, problem solving etc... Most students have background in these concepts h/w or s/w. Teaching hardware usually requires a more involved background in some EE, etc.... I didn't say that the s/w are any less intelligent, just less knowledgeable. < << Sorry for the flame, I'm just tired of interviewing smug new CS <<students who know nothing about reality and using the right tools for the <<job. They make great followers, but we desparately need thinkers and leaders. < <Have you ever thought about trying to HELP these "smug new CS students" by <giving them some of your ideas, or are you too tied up trying to rewrite soft- <ware you want to reuse? :-) No, between teaching, lecturing, assisting new students, managing a software team to 'do it write', and taking on the brain-damaged instructors who created these students, I don't even get to write much code at all anymore. Besides, I much prefer recycled software to re-used software :-) -ed cetron cetron@wasatch.utah.edu
darin@nova.laic.uucp (Darin Johnson) (05/17/89)
> Still, IMHO (for the second time) the use of GOTOs should be >minimized whenever possible, since it generally does lead to harder-to- >read programs which are unmaintainable by anyone other than the programmer >(and often not even maintainable by him/her more than a couple of weeks >later)! Another point. GOTO's don't get along well with optimizers. Either the optimizer gives up on some optimizations, or it spends lots of extra time. Of course, in C, a break or continue cause the same problems to a lesser degree. Optimizers can usually do more with languages like Pascal and ADA, because loops are easily recognized, a FOR statement isn't shorthand for a WHILE statement, etc. Darin Johnson (leadsv!laic!darin@pyramid.pyramid.com) We now return you to your regularly scheduled program.
jlg@lanl.gov (Jim Giles) (05/17/89)
From article <24330@agate.BERKELEY.EDU>, by ked@garnet.berkeley.edu (Earl H. Kinmonth): }>(Definitions - structured: code developed by stepwise refinement using }>(ultimately) whatever low-level programming tools that are available. }>"structured": eliminating GOTOs from code, even where the GOTO is the }>most efficient method and is _AS_ readible and the proposed alternative.) } } As an historian, it is interesting to watch people in an allegedly hard } and objective "science" make statements that are essentially } ideological. Presumably even someone who is only computer literate can } recognize the definitions of "structured" given here as essentially } ideological. As a non-historian, it is interesting to watch people who are allegedly historians make such obviously unchecked remarks. The description I gave of the meanings of 'structured' is an accurate account of the change in the use of the term. To be sure, the _new_ meaning of the term is almost purely ideological. Therefore, I suppose, pointing out the historical shift in the meaning is also ideological - _BUT_ the meaning of the term _DID_ shift. (And, if you'd bothered to check the literature on the subject, you would have seen that my original description is an accurate characterization of the change.) } Earl H. Kinmonth } a decade of C programming, and I've yet to use a goto since I } gave up FORTRAN for Lent. Incidently, if I'm not allowed to make ideological remarks, why are you?
ked@garnet.berkeley.edu (Earl H. Kinmonth) (05/17/89)
In article <13765@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >From article <24330@agate.BERKELEY.EDU>, by ked@garnet.berkeley.edu (Earl H. Kinmonth): >As a non-historian, it is interesting to watch people who are allegedly -------------------------------------------------------------------| Nothing alleged. I was hired as an historian and am paid as an historian, however much I might like to be paid at the generally higher rates prevailing for computer science types in the UC system. >Incidently, if I'm not allowed to make ideological remarks, why are you? What's your problem? I said I found ideological comments under the guise of objective statements "interesting." You may interpret that as meaning whatever you will, but "interesting" is "interesting!" HOWEVER, putting on a different hat, as a C programmer, I would deeply appreciate it (as an amateur C programmer) if those who assert the merits of one style over another provide definitions of (a) efficiency; (b) ease of maintenance; (c) criteria for measuring (a) and (b). Without these, the debate becomes the equivalent of the flame wars that occur every couple of months in the "editors" newsgroup. There, about every two months, one gets a round of - "only twits use vi, only dweebs use emacs." I would presume, perhaps naively, that the professional and would-be professional C programmers in this group would be able to provide an amateur such as myself with an objective set of criteria, perhaps a test suite or two, to measure, according to well-defined criteria, the relative advantages and disadvantages of alternative programming styles. If not, the whole discourse is pointless and should be moved to one of the "religion" or "consciousness" news groups.
mike@arizona.edu (Mike Coffin) (05/17/89)
From article <554@laic.UUCP>, by darin@nova.laic.uucp (Darin Johnson): > Another point. GOTO's don't get along well with optimizers. Either > the optimizer gives up on some optimizations, or it spends lots of > extra time. There is no reason that gotos should cause problems for a compiler, unless the programmer uses them to produce irreducible flow graphs. In particular, using gotos to break out of nested loops should not cause problems. If the mere presence of a goto causes the the compiler to give up, it isn't much of a compiler. > Of course, in C, a break or continue cause the same problems to > a lesser degree. Break and continue do not create irreducible flow graphs. > Optimizers can usually do more with languages like Pascal and ADA, > because loops are easily recognized, a FOR statement isn't shorthand > for a WHILE statement, etc. Modern optimizing compilers generally turn everything into a graph of basic blocks almost immediately. The optimizations depend on the topology of the resulting graph, not where it came from. In particular, the standard algorithms for data-flow analysis require the graph to be reducible, so may compilers punt if they are given an irreducible flow graph. See any of the standard compiler books for details. -- Mike Coffin mike@arizona.edu Univ. of Ariz. Dept. of Comp. Sci. {allegra,cmcl2}!arizona!mike Tucson, AZ 85721 (602)621-2858
kay@warwick.UUCP (Kay Dekker) (05/18/89)
You know, if I'd had any idea that people would start a "Tis/Tisnt" over GOTO, I wouldn't have posted the original article. More heat, less light. I can't wait for the pro/anti debate to become as futile as the (proverbial) angels on the head of the pin. Sigh. Kay the Crisco Kid: nasty pinko faggot agnostic pervert punk. csx043@uk.ac.cov.cck
bill@twwells.uucp (T. William Wells) (05/19/89)
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
bill@twwells.uucp (T. William Wells) (05/23/89)
In article <1826@wasatch.utah.edu> cetron@wasatch.utah.edu (Edward J Cetron) writes: : In article <912@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes: : >And if one insists on not putting this into its own function (making : >the return improper): : > : > for (i = 0; i < N; ++i) { : > for (j = 0; X[i][j] == 0; ) { : > if (++j == N) { : > printf("The first all-zero row is %d\n", i); : > break; : > } : > } : > if (j == N) { : > break; : > } : > } : > : >One could, of course, turn the first break into a goto, but : >eliminating the possible cost of the j == n test isn't worth the loss : >of clarity. : : AHA! But what if it WAS a function? And what if it was some sort of very : heavily used function? In THAT case wouldn't that fact that you saved : that extra useless code be worth something? Are you brain-dead? Or just blind? (Like me?) This is also from the article you quoted: for (i = 0; i < N; ++i) { for (j = 0; X[i][j] == 0; ) { if (++j == N) { printf("The first all-zero row is %d\n", i); return; } } } And is perfectly appropriate for putting into a function. --- Bill { uunet | novavax } !twwells!bill
kannan@babcock.cerc.wvu.wvnet.edu (R. Kannan) (05/28/89)
From article <1814@ubu.warwick.UUCP>, by mirk@warwick.UUCP (Mike Taylor): > In article <3, I think> gould@rosemary.cs.reading.ac.uk (Adrian Gould) writes: >> Lets eradicate the GOTO from all languages. > > I hate it when people say things like that; As if you can just wave a > magic wand over a language by excising GOTO, and everything will be > alright. Listen, just 'cause Quiche-eater Wirth connected GOTOs with > Mike Taylor - {Christ,M{athemat,us}ic}ian ... Email to: mirk@uk.ac.warwick.cs > Unkle Mirk sez: "G G7/B C F G G7/B B7 Em; Dm7 G7/B C Gdim7 G D C Gdim7 G D Cm" Dear Dr. Mike Taylor, I agree 100% that GOTO has been subject to very unfair criticism. The example you have given, does good. But your comparison with Ada exception handling feature really is completely out of line. Can you clarify further, why Ada exception handling should be considered just as another glorified GOTO package. Please educate me in this regard. --kannan
mirk@warwick.UUCP (Mike Taylor) (06/02/89)
In article <chicken> kannan@babcock.cerc.wvu.wvnet.edu (R. Kannan) writes: > I agree 100% that GOTO has been subject to very unfair criticism. > The example you have given, does good. But your comparison with Ada > exception handling feature really is completely out of line. Can you > clarify further, why Ada exception handling should be considered just > as another glorified GOTO package. Well, you've got to stand back from the glorious DoD fanfare, (or is it MoD?), and look at what the language really has to offer. Like IBM's PC, once you take away the badge, nothing much. It's the only language I know that has only ONE control-structure; unconditional GOTO. I mean, OK, dress it up a bit, represent it by a right-pointing arrow, whatever, but at the end of the day, they're not fooling anyone, and I know GOTO when I see it! Oh dear, I'm terribly sorry, I've just realised I'm talking about APL, not ADA :-) :-) :-) Seriously though, ask yourself, what IS exception handling? It's just saying, "When event E occurs, go to code section C, whatever else you're doing". S'a lot like catching signals in C. All that frogging about with setjmp() and longjmp() gets represented as something clever, something for "real programmers", and most people seem to swallow the idea without flinching, and more importantly, _without_ _THINKING!_ This is what I really object to, I guess. I mean, C is much more my field that ADA, so don't get the impression that I really know what I'm talking about (1/2 :-), but certainly I have come across the sort of attitude a lot of the while that says that once you dress GOTO up a bit, call it something different, (longjmp() in this case), everything is OK. I hope that everyone reading this knows deep down inside that it is just as possible to abuse "while", "for", "do", "longjmp()" or whatever other control structure you use, as it is to abuse GOTO. It is _easier_ to abuse GOTO, partly because many of us learned our programming on machines where that was all we had. But at the end of the day, control structures are supposed to be tools, and if we're irrationally afraid of one of them, then it's not gonna help us. "All [control structures] are permissible to me -- But I will not allow myself to be mastered by any!" -- Apostle Paul, 1 Corinthians On an only vaguely related note -- the one thing that annoys me about C is that you can't do n-level breaks. If Bourne shell (:-P) can manage it, I'da hoped C could! ______________________________________________________________________________ Mike Taylor - {Christ,M{athemat,us}ic}ian ... Email to: mirk@uk.ac.warwick.cs "istrcmp() -- Naughty but nice! ... Why isn't my program working?" - Sunny