Is it just me, or do restarts sound a bit like coroutines combined with ADTs? In Python or JavaScript, you can use the yield keyword to “yield” control to the calling code along with a current result. If the yield type was an enum/variant (for example, a result), then it would be similar to the concept of a restart.
This could work, I think, but you'd introduce a lot of complications and costs. Comparable to the decision to use exceptions (and some kind of try/catch) versus error propagation. Every single caller between the handler and condition site has to be able to handle both the happy path (got a result) and unhappy path (got a condition).
Another issue is just in performance. In an error or try/catch system you unwind the stack along the way. In a condition system, you don't. If you insisted on manually passing them up until you find a handler (or not, in which case it may become an effective noop), you have to touch all of that "is it a condition or result" logic all the way up, and then resume all the way back down, and then return to the top of a loop because you could get another condition. So you'd end up writing something more like this:
do {
result = call(...);
if is_condition(result) {
// possibly handle it or re-yield
switch(result) {
log: ...
other_condition: ...
default: yield result;
}
}
} while(is_condition(result));
It should work, but it seems like it would be unpleasant to work with. With a condition system, you may implement it in a way that forces this kind of costly search through the call stack, or you could register the handlers and avoid this costly backtrack and resume operation.
> Every single caller between the handler and condition site has to be able to handle both the happy path (got a result) and unhappy path (got a condition).
This isn’t terrible, 2 relatively popular languages, Rust and Go, do not have exceptions and do require the caller explicitly handle errors. Rust even has a question mark operator to make error handling this way a bit more ergonomic.
> Another issue is just in performance. In an error or try/catch system you unwind the stack along the way. In a condition system, you don't.
That makes sense. I’m curious if this is something that can be optimized statically by a compiler.