From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Tiny proposal for named loops.
Organization: Computer Science, University of Melbourne, Australia
Date: Tue, 25 Aug 1992 16:54:20 GMT

rmartin@thor.Rational.COM (Bob Martin) writes:

>Chuck.Phillips@FtCollinsCO.NCR.COM (Chuck Phillips) writes:
>
>|Two reasons for using goto's (break's, continue's, return's):
>
>|	1. Maintenance: Code what you mean, and mean what you code.  It's
>|	   easier on others.  If you *mean* "get out of this loop", use
>|	   "break" if you can, goto if you can't.  Restructure your code to
>|	   avoid *both* state variables and goto's if you can, but it you
>|	   can't, be straightforward.
>
>Consider this:
>
>	while (1)
>	{
>	   if (something)
> 		break;
>	}
>
>clearly "while (1)" does not fall under your advice to "code what you
>mean".  However, by using a flag, you can put "what you mean" in the
>loop condition.

I disagree. If find while(1), or more preferably for(;;), to indicate
quite clearly what the programmer means.

If the termination condition for a loop is complex, then
it should be coded as simply as possible - this means using
goto/break/etc - and documented with comments.

Don't obfuscate your code with confusing state variables when a simple
"break" will do - just make sure that you EXPLAIN the loop with a
comment!

>|Exercise: Try coding a Finite State Machine for arbitrarily length input
>|without using gotos.  

I have done that before, no problems.
While we're on the subject of FSM's and gotos, have a look at this code
taken from my Turing machine simulator program. This is another good
example of where gotos are useful. Try rewriting this without gotos!
(Solutions using exceptions don't count - at least, not until my compiler
implements them!)

The following code is exactly as I wrote it about 12 months ago.
It's a bit too long for a single function, but without exceptions,
the error handling makes things messy if you split it into multiple
functions. I suppose you could use longjmp to fake them in this case... yuck.

istream& operator>> (istream& input, transition_function& t) {
    state s, new_s;
    symbol sym, new_sym;
    dirn dir;
    char c = 0;

    // initialize the transition to be completely undefined
    t.initialize();

    // add transitions
    while(input) {    // keep searching until file error ...
        input >> s;
        if (input.eof()) break;    // ... or end of file
        input >> c; 
        if (c != ':') goto input_error;
        while (input >> c, c == '{') {
            input >> c;
            switch(c) {
                case '_': sym = Blank;    break;
                case 'B': sym = Blank;    break;
                case 'a': sym = A;        break;
                case 'b': sym = B;        break;
                case 'c': sym = C;        break;
                default : goto input_error;
            }
            input >> c;
            if (c != '/') goto input_error;
            input >> c;
            switch(c) {
                case '_': new_sym = Blank;    break;
                case 'B': new_sym = Blank;    break;
                case 'a': new_sym = A;        break;
                case 'b': new_sym = B;        break;
                case 'c': new_sym = C;        break;
                default : goto input_error;
            }
            input >> c;
            switch(c) {
                case 'L': dir = Left;    break;
                case 'R': dir = Right;    break;
                default : goto input_error;
            }
            input >> new_s;
            input >> c;
            if (c != '}') goto input_error;

            // now actually add the transition

            if (t.is_defined(s, sym)) {
                cerr << "Error: duplicate transition (machines must be "
                        "deterministic)\n";
                return input;
            }
            t.set_trans(s, sym, new_s, new_sym, dir);
        }
        if (input.eof()) break;

        // we always get one character to many
        input.putback(c);
    }
    return input;

input_error:
    cerr << "Syntax error reading transition function\n";
    return input;
}
-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.lang.c++