I agree that if you had to write the ifs by hand it would be a pita. Looking at you, Go.
Did you maybe mean "the checked type"? In that case I still think it's not equivalent because at least in Rust you can automatically transform the error while it bubbles up, while I don't know of a language with checked exceptions that lets you transform the exception while unwinding (short of manually catching, transforming, and re-throwing).
As far as I know, that's how Java's "throws" method signature works, which has been widely regarded as a mistake.
Don't check the return value of a call to the same API multiple times. Make it such that all calls to the API go through the same code that you write, so you have to check the return value only "once". This may sound extreme, but it's pretty close to what you can realistically achieve.
You can achieve that trivially by exiting if something goes wrong when calling the API. And where exiting is not possible because it's a longer running application, concerns have to be separated: If there are multiple pieces of code that need the same data, feed those pieces the data they need from a central location that interfaces with the API. And have the error handling logic (which is usually higher level control logic) in the central location.
like Railway Oriented Programming
https://www.youtube.com/watch?v=45yk2nuRjj8
I believe that almost every thing should return Result<T>, because almost everything can fail and compiler should scream when you do not handle those fail pathes.
That makes me believe that C#'s "FirstOrDefault" for value types sucks, because you're never sure whether the "Default" comes due to lack of value or because the found value is actually the same as default
e.g
var list = new List<int> {1,2,3};
var found = list.FirstOrDefault(x => x < 1);
found = 0 (default)
meanwhile 0 may be valid value! so we aren't sure whether it is error or an actual value
and we have to perform e.g casts to `int?` or stuff to detect that.
using Result<T> gives very precise information
This function is useful when you don't really care whether it's an error or the value. Imagine you're querying the view count of an item of the user. If the user is anonymous, the select might give an empty result, but you only care about showing a number to the user. So 0 is absolutely fine in that case.
If it's important to you whether the item actually exist, you're using the method in the wrong place.
First returning Result<T> or something like FirstOrNull would be better, because FoN would work for ref types - classes and stuff the same way (afaik) as FoD does, but it'd make error handling for value types like ints more precise
#define CHECK(com_expr) hr = (com_expr); if (FAILED(hr)) { return hr; }
Ah, the memories... glad I don't have to touch it ever again. "And a million other things that, basically, only Don Box ever understood, and even Don Box can’t bear to look at them any more".Even if they are eventually wrapped in .NET libraries.
https://docs.microsoft.com/en-us/cpp/cppcx/exceptions-c-cx?v...
https://github.com/microsoft/wil/blob/5a21cac10640f54b7ef886...
https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-a...
throw new ErrorUser('Bad input')
-> Show friendly error messages.
throw new ErrorFatal('Db unavailable')
-> Email error to dev and quit.
I never like the verbosity of returning errors from each methods.
How hard is it to trace the stack when you're supposed to be using error logging tools like Sentry?