That's a good solution. The next problem is that many code patterns, such as state machines, if naively converted from `goto` to `call()` will consume a lot of unnecessary stack space. This might not be a problem with a language/compiler that supports tail call optimization.
Right. Absent TCE and inline functions (the latter is now pretty much bog standard in every language in popular use, at least every compiled language), goto for state machines and similar uses can be much more efficient and also handle the concern of blowing up your stack. If you have TCE and inline functions, then mutual recursion is a perfectly efficient way to handle that kind of situation that is often (but not always) clearer than goto. And if you pair that with nested functions so that you can close over some common lexical scope, you eliminate the need to use global variables or to thread data through each function call (keeping your parameters to a minimum).
In plenty of environments, there's a very limited number of calls you can make before the program fails entirely. For instance, in GW-BASIC, your namesake, the limit is less than 100 calls. There are plenty of real useful production langauges where your stack will run out before 1000 frames of depth.
But on the other hand, it's quite reasonable to write a state machine which is expected to make [mb]illions of state transitions.
When I wrote in GW-Basic, I only used gotos. Most of the example code that I had access to used gotos.
I was 11 years old at the time.
> There are plenty of real useful production langauges where your stack will run out before 1000 frames of depth
That wouldn't surprise me in an embedded environment. But if that's the case for a run of the mill general purpose programming language that's running a typical web application, I'd be shocked.