chris@mimsy.UUCP (Chris Torek) (07/25/87)
In article <960@fmsrl7.UUCP> grazier@fmsrl7.UUCP (Kevin Grazier) writes: >On a more intangible level, I seem to remember being taught as an undergrad >that there are still a COUPLE (and I mean just that) algorithms that >can't be done without a goto. To prove otherwise to yourself, consider any program that contains at least one `goto' statement. The section of code to which this branches is either normally reachable, or reachable only by a goto. (The following may be flawed; I have not bothered to check it carefully. Nonetheless the general idea ought to be right.) Case I: Normally reachable. Replace the beginning of the program with while not prog_done do and the end of the program with if not doing_goto or did_goto then prog_done <- true; fi; end while; Now protect every single statement except those which would be executed by the `goto' with if not doing_goto then <original statement>; fi; At the beginning of the section performed by the goto, add if doing_goto then did_goto <- true; fi; Change the goto statement to doing_goto <- true; Add two global variables: boolean doing_goto <- false, did_goto <- false; Case II: Not normally reachable. Move the unreachable code anywhere within the scope of the main program and protect it with `if not doing_goto then <code>; fi;'. The problem has now been reduced to case I. This can be repeated for all remaining goto statements, using different variable names for the pair of booleans. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mi (Ssed to
chris@mimsy.UUCP (Chris Torek) (07/26/87)
In article <7687@mimsy.UUCP> I mentioned >(The following may be flawed; ... It sure was. >Nonetheless the general idea ought to be right.) ... which I still think is true. The general idea, in case it was obscured by the (bogus) details, is to add enough booleans and, if necessary, a loop around the entire program, so that each goto can be replaced by a sequential flow to the place to which the goto went, where the gone-to code then executes. Doing this is nontrivial, but, I think, always possible. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mimsy!chris
kopaz@rdlvax.UUCP (John Anthony 'Echo' Kopaz) (07/28/87)
Posting-Front-End: GNU Emacs 18.47.1 of Thu Jul 9 1987 on rdlvax (berkeley-unix) in your article you write: >To prove otherwise to yourself, consider any program that contains >at least one `goto' statement. The section of code to which this >branches is either normally reachable, or reachable only by a goto. >(The following may be flawed; I have not bothered to check it >carefully. Nonetheless the general idea ought to be right.) >Case I: Normally reachable. >Replace the beginning of the program with > while not prog_done do >and the end of the program with > if not doing_goto or did_goto then prog_done <- true; fi; > end while; >Now protect every single statement except those which would be >executed by the `goto' with > if not doing_goto then <original statement>; fi; >At the beginning of the section performed by the goto, add > if doing_goto then did_goto <- true; fi; >Change the goto statement to > doing_goto <- true; >Add two global variables: > boolean doing_goto <- false, did_goto <- false; >Case II: Not normally reachable. >Move the unreachable code anywhere within the scope of the main >program and protect it with `if not doing_goto then <code>; fi;'. >The problem has now been reduced to case I. >This can be repeated for all remaining goto statements, using >different variable names for the pair of booleans. -- i don't think all that warped boolean logic is in the best interest to readable code. it has a FORTRAN :~{ flavor to it. in the interest of readability, maintainability, and flexability .... (and a couple 'bilities i may not have mentioned :~)) i think that gotos could be justified. to say otherwise is to limit a ^^^^^^^^ - not are or should be choice in your professional behavior. (that is not very professional.) there are three distinct aspects in program design: data structures, algorythms, and languages. all of which impact on the others. limiting a choice in one will limit choices in the others. another way of looking at it is thus: The Law of Requisite Variety the factor with the most choices will be the dominant (say: controling) factor. 1 choice -> robot 2 choices -> delemma 3+ choices -> FREEDOM!!! this is my opinion, you are not required to agree/disagree, it is just the way i design. tanx. echo. -- john a. kopaz [aka echo.] associate research scientist / software engineer / test specimen voice: 213-410-1244 -- fax: 213-216-5940 -- corporeal: rdl arpa : kopaz@rdlvax.rdl.com 5721 w. slauson ave. uucp : ...!{psivax,csun,sdcrdcf,ttidca}!rdlvax!kopaz culver city, ca 90320
stuart@bms-at.UUCP (Stuart D. Gathman) (07/28/87)
Knuth has an excellent method for converting any program, no matter how convoluted, to perfectly structured code with no goto's. The following pascal template will give you the idea: PROGRAM DOANYTHING; VAR P : INTEGER; BEGIN WHILE P != 0 DO BEGIN IF P = 1 THEN BEGIN (* DO STEP 1 *) P := (* STEP TO PERFORM AFTER 1 *) END; IF P = 2 THEN BEGIN (* DO STEP 2 *) P := (* STEP TO PERFORM AFTER 2 *) END; IF P = 3 THEN BEGIN (* DO STEP 2 *) P := (* STEP TO PERFORM AFTER 3 *) END; (* NOTE: SET P TO 0 WHEN DONE *) END; END. -- Stuart D. Gathman <stuart@bms-at.uucp> <..!seismo!dgis!bms-at!stuart>
tdavis@athena.mit.edu (Timothy L. Davis) (07/29/87)
In article <465@bms-at.UUCP> stuart@bms-at.UUCP (Stuart D. Gathman) writes: > >Knuth has an excellent method for converting any program, no matter how >convoluted, to perfectly structured code with no goto's. >... > IF P = 1 THEN > (* DO STEP 1 *) > P := (* STEP TO PERFORM AFTER 1 *) > IF P = 2 THEN > (* DO STEP 2 *) > P := (* STEP TO PERFORM AFTER 2 *) >... I am just finishing a modification of a program which used this precise system for "computed" gotos. What a mess! It was nearly impossible to read clearly. The little assignment statements, which were in effect gotos, were MUCH harder to follow than goto's themselves. If you are going to write spaghetti code, you might as well use the spaghetti construct! Tim Davis tdavis@ATHENA.MIT.EDU ...mit-eddie!mit-athena!tdavis
rpw3@amdcad.AMD.COM (Rob Warnock) (07/30/87)
In article <1217@bloom-beacon.MIT.EDU> tdavis@ATHENA.MIT.EDU (Timothy L. Davis) writes: +--------------- | In article <465@bms-at.UUCP> stuart@bms-at.UUCP (Stuart D. Gathman) writes: | >Knuth has an excellent method for converting any program, no matter how | >convoluted, to perfectly structured code with no goto's. | I am just finishing a modification of a program which used this precise | system for "computed" gotos. What a mess! It was nearly impossible to read +--------------- This is *precisely* what led Bill Wulf (over a decade ago) to publish ago a short note in ACM SIGPLAN(?) entitled "Global Variable Considered Harmful" (following Dijkstra's earlier paper "Goto Considered Harmful"). It is not the "goto" per se which is harmful, but the spagetti control flow which results from an undisciplined use of it, and the resulting human difficulty in proving that all possible combinations of that control flow yield the correct results. (Also see Miller's classic "The Magical Number Seven Plus Or Minus Two".) Remember, Dijkstra's definition of "structured programming" was *not* a simplistic "no gotos", but rather an unceasing vigilence against all manner of "complexity generators". Global variables (*all* global variables) create the same potential for unbridled complexity. On the other hand, while "no gotos" and "no global variables" are very useful heuristics, following them doesn't guarantee success. Murphy's Something-Or-Otherth Law: "It ain't that simple." Rob Warnock Systems Architecture Consultant UUCP: {amdcad,fortune,sun,attmail}!redwood!rpw3 ATTmail: !rpw3 DDD: (415)572-2607 USPS: 627 26th Ave, San Mateo, CA 94403
farren@hoptoad.uucp (Mike Farren) (07/30/87)
Seems to me that IBM, while not normally considered C experts, have something to say about the "no gotos/no globals" controversy: THINK! I can't see any reason not to use a goto if it makes my program flow more legible (and that's to ME, not to a hypothetical optimizing compiler - all the optimization in the world isn't going to help if I'm confused as to the basic data flow). Likewise, I can't see any reason TO use one if other constructs are available that work as well, have less undesirable side effects, and are clear. The ultimate goal, I think, is to produce programs which are error-free and maintainable, and in pursuit of that goal, I will use any constructs available to me in the language I'm working with. -- ---------------- "... if the church put in half the time on covetousness Mike Farren that it does on lust, this would be a better world ..." hoptoad!farren Garrison Keillor, "Lake Wobegon Aq----
chris@mimsy.UUCP (Chris Torek) (07/31/87)
In article <105@rdlvax.UUCP> kopaz@rdlvax.UUCP (John Anthony 'Echo' Kopaz) writes: [regarding mechanically removing goto statements by adding booleans] >i don't think all that warped boolean logic is in the best interest to >readable code. Certainly not. But someone made the claim that there are algorithms that require goto statements; this is not the case. On the other hand, modern imperative languages have all the constructs they do for good reason: You can write what you mean. Clear code requires two things: knowing what you mean; and writing that. If you *really mean* `go do something special', by all means, write that. But if you mean something that can be expressed *simply* (this is important) using a weaker construct (`weaker' here means `less able to affect control flow': `while' is weaker than `goto'), use the weaker form. It says less, and hence is easier to understand. A loop that reads while ((in = getinput()) != END_OF_INPUT) (*op[in])(in); is using a very strong control operation, yet may well be easier to understand than a whole series of weak `if's: while ((in = getinput()) != END_OF_INPUT) { if (in < 4) { ... } else if (in == 4) { ... } else if (in < 7) { ... } ... } Deciding when the stronger construct makes the code clearer is an art, and different people will certainly have different aesthetics. So what else is new? :-) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mimsy!chris
rblieva@cs.vu.nl (Roemer b Lievaart) (07/31/87)
Although I usually hate goto's, here is an example which I used
myself two or three times:
switch( expr ) {
defolt:
default: /* code, probably error handler */
break ;
const1: ...
const2: if ( ! const2_allowed )
goto defolt ;
else ...
const3: ...
...
}
Now this is just another example which seems to me perfectly
readable. But I must say, far most goto's I find detesting.
Yech!
One shouldn't get used to goto's, that's my opinion.
Let's live,
Roemer B. Lievaart...
Amsterdam.
Q: How many IBM cpu's does it take to do a logical right shift?
A: 33. 1 to hold the bits and 32 to push the register.