Re:Goto Is Not a Horror
by o11c on Wednesday March 20, 2024 @10:49PM
(#39774478)
Good uses of `goto` generally fall into the following categories:
* C-specific compiler-independent cleanup. This is completely unnecessary if your language supports proper destructors. Unfortunately many still-used and newly-invented languages are completely insufficient here. GNU C has `__attribute__((cleanup))` but it's kind of clunky.
* `continue` or `break` for an outer loop. One of the few things Java did correctly was supporting this directly, with names. A few languages support break/continue by number which is error-prone (fortunately they don't make the same mistake C did in adding `break`-skew for `switch, though unfortunately that usually means they also give up on efficient multi-way dispatch)
* nontrivial variants of `fallthrough` for a `switch`. This is generally an indicator that you should refactor out an `inline` function, but sometimes that makes the code significantly uglier since most languages don't support local-promoted-dynamic variables.
* computed `goto` in interpreter loops, state machines, etc. There is no viable replacement for this, though if your compiler is capable of inlining through an array of function pointers that helps (last I checked, GCC and Clang both failed very badly).
* coroutine implementations. Efficient coroutines have to be built-in to the language anyway (so they can optimize the existence of locals), but languages that support coroutines tend to abandon sanity all ye that enter here.
* C-specific compiler-independent cleanup. This is completely unnecessary if your language supports proper destructors. Unfortunately many still-used and newly-invented languages are completely insufficient here. GNU C has `__attribute__((cleanup))` but it's kind of clunky.
* `continue` or `break` for an outer loop. One of the few things Java did correctly was supporting this directly, with names. A few languages support break/continue by number which is error-prone (fortunately they don't make the same mistake C did in adding `break`-skew for `switch, though unfortunately that usually means they also give up on efficient multi-way dispatch)
* nontrivial variants of `fallthrough` for a `switch`. This is generally an indicator that you should refactor out an `inline` function, but sometimes that makes the code significantly uglier since most languages don't support local-promoted-dynamic variables.
* computed `goto` in interpreter loops, state machines, etc. There is no viable replacement for this, though if your compiler is capable of inlining through an array of function pointers that helps (last I checked, GCC and Clang both failed very badly).
* coroutine implementations. Efficient coroutines have to be built-in to the language anyway (so they can optimize the existence of locals), but languages that support coroutines tend to abandon sanity all ye that enter here.