Remix.run Logo
sshine a day ago

There is some DX similarity between checked exceptions and Result types.

Because the compiler will fail if you don't explicitly mention each possible exception.

But checked exceptions are coming out of style: They're unchecked in C#, and frameworks like Spring Boot in Java catch all checked exceptions and rethrow them as Spring Boot flavored unchecked ones.

For unchecked exceptions and Result types:

The DX is very different in one critical way:

With Results you constantly have to differentiate between error and ok states, before you proceed. With unchecked exceptions you generally assume you're always in an ok state. It's equivalent to wrapping your whole function body in 'try { ... } catch (Exception e)'. And you can get that with Result types in Rust by using '?' and not worry about doing something half-way.

Ultimately: Are you a happy-path programmer?

Arnavion a day ago | parent [-]

>Because the compiler will fail if you don't explicitly mention each possible exception.

But only the first time. Once you add `throws FooException` to the caller signature, the compiler won't complain about any future callees that also happen to throw FooException, even if you did care about handling their exceptions yourself. With callees that return Result you do get to make that decision for every callee.

sshine an hour ago | parent [-]

That's a fair distinction.

I would say "adding Result to the caller signature" provides a similar cascade, but it's not entirely true: Every call must separately be unwrapped. So consistently wrapping your Result calls with the '?' operator is similar to a gigantic try-catch block or adding 'throws CheckedException' everywhere.

So both the '?' operator and adding 'throws CheckedException' everywhere let you accidentally neglect proper error handling: You have a default that is syntactically almost invisible and frees you from thinking. The checked exceptions give you a little more freedom from thinking than the '?' operator.