They're essentially callable, stateful, structured gotos. Difficult to understand for the uninitiated.
For example, generators. Also known as semicoroutines.
https://langdev.stackexchange.com/a/834
This:
generator fib() {
a, b = 1, 2
while (a<100) {
b, a = a, a+b
yield a
}
yield a-1
}
Becomes this: struct fibState {
a,
b,
position
}
int fib(fibState state) {
switch (fibState.postion) {
case 0:
fibState.a, fibState.b = 1,2
while (a<100) {
fibState.b, fibState.a = fibState.a, fibState.a+fibState.b
// switching the context
fibState.position = 1;
return fibState.a;
case 1:
}
fibState.position = 2;
return fibState.a-1
case 2:
fibState.position = -1;
}
}
The ugly state machine example presented in the article is also a manual implementation of a generator. It's as palatable to the normal programmer as raw compiler output. Being written in C++ makes it even uglier and more complicated.The programming language I made is a concrete example of what programming these things manually is like. I had to write every primitive as a state machine just like the one above.
https://www.matheusmoreira.com/articles/delimited-continuati...
What you've given is an example of how to implement a coroutine though.
Not of how to write a state machine based application without hiding the state machine behind abstractions.