Rethinking goto
Most programming languages have support for an if-statement1:
The if-statement is a branch which splits two directions: one direction for `true` and the other direction for `false`2. The code after the if-statement is executed regardless of which branch was taken, so in effect the two branches come together after the if-statement3.
Most of the languages I’ve encountered also define some variant of a switch-statement, which is the concept of an if-statement except generalized to any number of branches:
Just like the if-statement, control returns to a single path after the switch-statement.
But what about this example:
So far as I know, there is no language construct which can directly represent this idea, except that of `goto`.
Here is another, slightly more complicated, example:
It’s difficult to come up with a simple program that follows this flow without repeating condition checks or other some other unnecessary overhead. Again, the answer may be to use a `goto` in this case.
But practically, when would you ever run into a complicated branching construct that doesn’t fit so well into `if` or `switch`? Well, lets look at this often-required-but-difficult-to-implement flow:
I’ll call this the “error-branch statement”, because I don’t know of a better term for it. A sequence of operations needs to be performed, and each may fail to common error branch. If we say that a switch-statement generalizes an if-statement to have multiple alternative branches with one condition, the error-branch statement generalizes an if-statement to have multiple conditions with a single alternative “else” branch.
A try-catch-statement could be used to model this behavior, but there are many situations where exceptions are more trouble than they’re worth. This is particularly true in code embedded on a microcontroller that needs to run indefinitely, which is the type of code I deal with quite often. And an error-branch-statement would probably be a more idiomatic fit into a language like C than exception handling would.
Here’s another type of error handling branch I would find handy in low-level language like C:
I broke convention here and changed physical orientation of the error handling flow path because it fits better. This is the same case as the error-branch statement before, except each operation requires different cleanup code if it fails. For example, if operation 1 is to open a file, cleanup 1 might be to close the file again, etc.
In C# this type of branching is achieved by a `using` statement and exceptions. In C++ this type of behavior is achieved using RAII and exceptions. In C there is no direct way of representing this, despite the fact that I’ve seen this pattern more often in C than any other language. In C you have to settle: either goto, nested ifs, function calls, error state variables, etc. None of them is quite the right fit, and the code reads as if it were more complicated than it really is.
What about the other flowcharts I presented earlier? Why can’t we represent those using structured-programming constructs? Well, you can’t define a new branching statement for every possible flowchart, so instead we need a generic mechanism to handle arbitrary cases. In C this is the `goto` statement: it allows us to define any arbitrary control paths for anything we want to.
Next time I’m going to dig deeper by discussing an alternative to `goto` which I’ve seen used quite often, for better or worse.