An alternative proposal to `try`/`catch`/`throw` error handling

Separating the factual and subjective

I think you need to separate two things:

  • Is something technically possible, equal in power or more powerful? [this is factual and testable]
  • Is something desirable to have in a language? [this is subjective, and based on desirability]

From a factual POV

try { .. }, without Ok-wrapping, is strictly more powerful because it gives you more possibilities than 'escape does.

This means that 'escape can't support type-based jump targeting since it is based on syntax alone, and that limits our design freedom.

This also means that it subsumes everything that 'escape can do wrt. library based experimentation with macros and whatnot.

From a subjective POV

Some possibilities may not be desirable... (Aside: type-based jump targeting is not how Java does exceptions, and it can't escape the function boundary, so it is not unwinding based or "full blown exceptions".)

You might think that we should limit our design freedom in some aspects (as you do with type-based jump targeting); and I agree that this is acceptable. My view is that we should limit freedom wrt. Ok-wrapping because Ok-wrapping is beneficial. I understand you will disagree with this point of view.

1 Like

I agree that 'escape by itself can not do this. But who says break for example could never learn this? So while strictly try {...} might be able to aquire this, so can a macro based solution.

And it's not like this isn't also working in the other direction: A macro can be shadowed, making it easy for a user to add, for example, tracing log output to all of them if they want. Shadowing builtin syntax would require a fully new feature.

Because if you have break 'escape expr as the basis on which your macros are built upon, then you have locked in the jump target, and it can't be anywhere else.

Using break expr without any sort of label is also problematic because of all the interactions with loops et al. which makes it all less expressive (because throw expr and expr? could disambiguate between loops and try { .. } whereas break without a label can't..).

This can still be done atop of try { .. } with a macro that you can then swap out, or by defining a different effect carrier than Result which has richer effects (this seems the more robust solution to change/extend the effect carrier type, especially if we get HKTs and with we can then define monad transformer-like structures..).

The macros can be adjusted. try { ... } and throw as proposed doesn't offer the funcionality either.

Yeah, but I'd have to swap out the try for the macro. With macros I can go to the source defining it, take it to my project, adjust it and all of them are going to be adjusted accordingly. Any type API based solution would also be more limited than AST based adjustments with macros.

But we're getting really off-topic here again. I'll make sure to add a clarification that the flexibility of 'escape concerns the discussed part of error handling functionality.

Unless the macro has access to a primitive mechanism like try { .. } it can't be adjusted in that way.

What I'm saying is that you'd define the macro as an abstraction in terms of try; when you have break 'try expr, then you get both the syntax based mechanism AND the type based mechanism.

Yes, Iā€™m talking about the feature of live-swapping parts of existing code.

Rust std has lots of methods called try_fold try_unwrap try_into etc.

Also, macros can add type assertions, as they can expand to, say, {let x = $arg; assert_try(&x); x}, where assert_try(&x) is fn assert_try<T: Try>(_x: &T) {}.

Iā€™ve now made an RFC out of the idea.

One big change is that the RFC uses escape {} blocks instead of 'escape: {} labels due to problems migrating existing code using labels and ?.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.