-
Notifications
You must be signed in to change notification settings - Fork 471
Description
background: https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227
with this feature, we will be able to do early returns and propagate errors as they arise, kind of like rust's question mark-operator. this has the same sort of effect as throwing an exception in that it will bubble up through all let?
assignments until the error is handled somehwere, just like exceptions.
the line between exceptions and errors thus blurs, basically resulting in two different syntaxes to do roughly the same thing, but requiring different handling methods somewhere on the caller's end.
the one place where this is not trivial to address is on the ffi boundary, where external functions may throw for various (and even unknown/unexpected) reasons, requiring you to handle exceptions in your rescript code.
as a suggestion to prevent exceptions and facilitate exception-free code (instead using Error
s and let?
s), some way of "wrapping" an ffi binding should be provided, e.g.:
@toResult
external somethingThatCouldThrow: string => string = "somethingThatCouldThrow"
// the above would be sugar for:
// let somethingThatCouldThrow: string => result<string, JsExn.t>
// it also needs to be able to handle `promise`s:
external somethingThatCouldThrowAsync: string => promise<string> = "somethingThatCouldThrowAsync"
// let somethingThatCouldThrowAsync: string => promise<result<string, JsExn.t>>
here, somethingThatCouldThrow
would be wrapped with a try-catch that catches all errors and returns them as Error<JsExn.t>
this would facilitate static analysis for unhandled Error
cases, as well as allow us to write exception-free code, moving towards a sane, predictable and exhaustive handling of errors (again, think rust).
we should also think through how this would apply to async ffi. the external call would have to be awaited inside the try-catch. what if it spawns another unawaited promise internally (global unhandled rejection)? does it make the rejection case redundant, or should Error
result in rejection with the error (then we won't be able to switch
on the result in .then
)?
let's discuss this and see if it makes sense and how it could be implemented.