ID:181336
 
There are cases when goto is the only solution without changing a lot things.

Anyways, that's similar to
That image is pretty old. I've had it as my Chatters' AFK Message for the longest time like months ago.

Never use goto.
You are perfectly capable of using it, but there really is no really desirable need to use it. It's bad practice and it makes your code look absolutely terrible.
For looping through lists, I use for().
For looping through a timer, I use while().

I never found the need for "goto", and I use while() the most, for() the second most.
In response to Maximus_Alex2003
There are some uses of the goto construct where a while()/for() would make less sense - implementing finite state machines is the canonical example.

But usually, yes, a structured construct is better.

(Incidental note: C has a pair of calls, 'setjmp' and 'longjmp', that let you jump across calling contexts - that is, you can jump from one function into a completely different function! The original intention was implementing interrupt handlers and exceptions, I think)
In response to Jp
Jp wrote:
There are some uses of the goto construct where a while()/for() would make less sense - implementing finite state machines is the canonical example.

How would goto make finite state machines better? I cannot think of a way goto would help with that.

In an object-oriented language, the best way to do an FSM would be to have objects for states. You can have a base class type for states in general, and give the state type functions for entry/exit actions, and they can handle themselves, and you can subclass the specific states as well for added versatility.
state
proc
init()
update()
entered()
exited()
transition()
or_whatever()

state/stateMachine
var/list/states
var/state/current

update()
current state transition/exit
new state enter/action/whatever

state/baddyWander
...
state/baddyAttack
...
state/baddyRunAway
...

state/stateMachine/AI
set up wander/attack/run states


In C, I would prefer a function for each state, a variable for the state, an array of state functions, and a table of transitions.
#define NUM_STATES 10
#define NUM_INPUTS 15
int state = 0;
outputType *stateAction[NUM_STATES](inputType);
int stateTransitionTable[NUM_STATES][NUM_INPUTS];

Then you can easily transition between states and execute the next one with
stateAction[stateTransitionTable[state][input]](stateInputTypes);

or something along those lines, and you can easily set up functions for state enter/exit actions and other fun stuff too.

I still wouldn't think goto would be a good use for this.

Still, even though I don't use goto at all, I will admit that I sometimes do other aweful things in the name of saving time and pushing forward with a project.

(Incidental note: C has a pair of calls, 'setjmp' and 'longjmp', that let you jump across calling contexts - that is, you can jump from one function into a completely different function! The original intention was implementing interrupt handlers and exceptions, I think)

Yes, that is correct. That is basically their only purpose, implementing better error handling in C, since there isn't any other good means of jumping scope. We are spoiled these days with exceptions, especially in Java.

It would be funny if there was a comic about "hardcore hackers" handling their data flow by programming something like a hard-coded stack overflow every time they wanted to branch. I would give a funny example, but I would have to unpack my systems programming book as I don't remember the order of stuff on a stack frame.
In response to Ripiz
Ripiz wrote:
There are cases when goto is the only solution without changing a lot things.

This just so happens to be the set of all cases where goto is already being used.

How convenient.
In response to Loduwijk
How would goto make finite state machines better? I cannot think of a way goto would help with that.

The specific use-case I'm thinking of is lexical analysis (which is basically constructing a finite state machine to recognise input and do stuff with it). Have a look at code generated by the likes of 'flex' or other lexer-generators some time - they use goto pretty often, and they generate much faster code than a human will.

The problem with the OO approach is that it's pretty slow (two virtual function calls on every state change, but with the added benefit of having even more memory usage than the table-based approach!) - and while performance usually isn't worth worrying about, for lexing it's deeply relevant, and state changes occur all the time while lexing.

My understanding of how one writes a fast lexer in C is that it looks something like this:
table_of_states[number_of_states][number_of_input_symbols] = {STATE_ONE, STATE_TWO etc.};

void fsm() {
  char input = get_input()

  int state = table_of_states[STATE_INITIAL][input]
  switch(state) {
    case STATE_ONE:
      STATE_ONE_HANDLER:
      while(true) {
        // Do state one stuff
        input = get_input()
        new_state = table_of_states[state][input]
        if(new_state != state) {
          state = new_state;
          switch(state) {
            case STATE_TWO:
              goto STATE_TWO_HANDLER;
            etc.
          }
        }
      }

      handlers for other states
  }
}


Basically you use goto to jump in and out of handlers for various states when necessary, and the states involved are tight loops. Lots of duplicated, deeply nested, ugly code. It's a performance thing, not a readability/maintainability thing - and usually you get a program to write it for you, rather than writing it yourself.

EDIT: Oh and it's probably important to note that I'm no expert and may well be barking up the wrong long-lived, leafy plant with a woody stem.
In response to Maximus_Alex2003
Maximus_Alex2003 wrote:
You are perfectly capable of using it, but there really is no really desirable need to use it. It's bad practice and it makes your code look absolutely terrible.
For looping through lists, I use for().
For looping through a timer, I use while().

I never found the need for "goto", and I use while() the most, for() the second most.

Obviously while and for are better ways to create loops, but as Jp suggested goto can be used for more than just loops. BYOND is limited in terms of flow control because it doesn't have exceptions. Break, continue, and return are sometimes insufficient, or at the very least they're less ideal than goto. Having to jerry-rig a break statement to do what you need can sometimes be messier than using a goto statement.

The good news is that the situations where break, return, and continue are not sufficient are rare. The use of goto is bad because its overuse can lead to messy code, but because these situations are rare goto's proper use will not cause problems.
In response to Jp
Ok yes, I see what you're getting at. I was thinking about readability/maintainability. If performance is a priority far and away above everything else, then your argument is not only valid but is accurate in some situations, like what you have described.

Since goto compiles/assembles into a single machine code instruction, obviously it is perfect if it exactly fits what you need. However, if you are trying to use it to simulate a loop and you're using your own if/goto pairs for this, the result will probably be strictly worse if your compiler does no optimization, as you will have two or three branches for the if statement and 1 for the goto and the redundant parts would not get optimized away, whereas the compiler would (assuming it's not a crappy compiler) guarantee a certain number of branches, just whatever is required for the loop. Though in a compiler that did optimize, an if/goto pair would likely end up getting optimized into the same form it changed a loop structure into.

For non-trivial control flow, like what you are describing with the performance-based lexer, that is obviously going to be better than normal control structures since that fits the use perfectly and we have nothing built in (other than goto) which can manage that.

It is funny that you bring up this topic, as I have been working with this topic recently and therefore can appreciate what you are getting at. I'm trying to make a Java-like language that is currently strictly worse than Java, and I'm only just recently getting to the point where I'm trying to optimize the assembled code, but even before this is taken into account my compiler still takes approximately as long as javac.exe takes to compile an equivalent Java program, so my entire product is strictly worse in every way so far. :( Perhaps it's because I'm not using goto! ;)