I posted under “help” because this is not a fully developed idea. I wish to see how people think about it before elaborating on it.
Reading through exception related posts, a really weird idea popped up in my mind: what if exception control flow can be resumed?
For example:
def invoke(fn: callable):
if not callable(fn):
fn = raise TypeError("Give me a callable")
return fn()
try:
print(invoke(None))
except TypeError:
resume lambda: "You got it!"
# prints: "You got it!"
In this example, keyword raise behaves like yield - it has an optional return value. A new keyword resume is used to return to the execution context where the Exception was raised. It optionally takes an argument as the return value of raise.
I’m pretty sure this has been suggested before, so you should probably hunt out the previous thread as there will have been issues raised in there that you’ll need to address.
Personally, I’ve never had a need for this sort of functionality, so I’m at best neutral on it.
I searched google, stackoverflow, github issues, this forum (and also asked ChatGPT). Did not find anything (I also feel that it should have been suggested, that’s part of reason why I initially posted under help topic).
That would be very difficult to implement, considering that exceptions can be propagated through C functions. Once a C function has returned, you can’t resume it.
To me it seems like you’d want the function throwing the error to opt into being resumable, otherwise every function that throws errors to deal with invalid state will have really strange behaviour. So if you already have to mark the code in some way, why not just directly use a generator instead?
Yeah. Although I’d go a slightly different direction for the same reason: an async function. They’re designed to be easily composable, and you can yield anything you choose to use, so you could design an event loop that permits this sort of resumability.
The important thing here is that exceptions aren’t resumable, but generator and async functions are. There’s a TON of infrastructure to make this happen, which could easily be used for this purpose.
What if the function has two or more raise expressions? How does the caller specify different values for the resume statement to correspond to different raise expressions?