5 ms·
> Any error system that relies upon developer discipline will fail because errors will be missed. Haven't there been some languages that force functions to ret
by tus89 6y ago
> Any error system that relies upon developer discipline will fail because errors will be missed.
Haven't there been some languages that force functions to return some kind of tuple like:
result,error
And forces the programmer to at least do:
if(error) {
}
It does not force any kind of correct handling, but simply oversights should be caught. I might be imagining things though.
- simias 6y agoThat's Go. IMO Rust's approach is vastly saner, since a Result<> type has to be explicitly handled one way or an other. You simply can't access the returned value without unwrapping it. Of course that leaves function that can fail but don't return any value, but since Result is tagged "must_use" you get a compiler warning if you don't explicitly discard the result with something like `let _ = foo()`.
- TacticalCoder 6y agoGP mentionned "maybes". In Haskell (and others) you have for example both maybe and either. When you've got an either you can have either (ah!) the left to indicate an error (and which error) or the right to hold the correct value. And the type system forces you to at deal with both cases (like a maybe forces you to deal with the case where it's "maybe not").
- masklinn 6y agoWhat you're describing is Go, except its requirements are much weaker than that. Rust, meanwhile, is way stricter than that, and has gone way further on the "not relying on developer discipline" path: a failing Rust function will return a `Result<Value, Error>`. You can't even access the value without explicitly checking whether it's a value or an error one way or the other, which you can very much do so in e.g. Go. Rust also has an attribute called `must_use`, which can be set on types and functions. That attribute causes the compiler to emit a warning if the marked object is not used at all (either the type or the function's result), so while go will not say anything if you write Foo() and that returns an error (or an error and a result you happened not to care for), Rust will absolutely complain by default in the same case, you will need to write at the very least let _ = Foo(); Go has a second issue, which is that in result, error := Foo() that you "have to" handle the error is a consequence of the unused variable check (can't define a variable and never read from it). However because it's that instead of something dedicated, this: id, error := Foo() result, error := Bar(id) if error != nil {} will work fine, with no complaint. Despite possibly passing complete nonsense to Bar if Foo is in error. Also works with id, error := Foo() if error != nil {} result, error := Bar(id) Funnily enough Rust will also warn in both those cases, because it tries to track individual writes.
- kelnos 6y agoThere's no "forcing" there. You can simply ignore the error part of the tuple, or even just forget to check it. If the function returns a (non-error) value that is directly accessible from the function call, the programmer is not forced to do anything with the error. This is exactly the same problem with null: forget a null check, and you're hosed. Forget an error check, and you're hosed. If you make errors a part of the actual single return type (as Rust does), then you have to explicitly deal with the possibility of an error before you are even allowed to touch the successful case.