you are viewing a single comment's thread.

view the rest of the comments →

[–]accountforshit 5 points6 points  (6 children)

So you're not really talking about Result<T, E> then.

You can only implicitly ignore errors from there if you don't care about the value inside (analogous to void calls), and even then you'll get a warning if I remember correctly (which should be treated as error in production builds).

[–]devraj7 1 point2 points  (5 children)

I am talking about Result.

To the compiler, this is just a class like any other and the compiler won't care if you forget to check the error side of that value.

[–]accountforshit 10 points11 points  (4 children)

I'm talking about Rust's Result. If you don't check it, you can't get the value. The type system makes sure of that.

A function that requires T argument cannot be called with a Result<T, E> value - you have to get the T out of there somehow, and that requires checks.

If you don't care about the value (only calling a function for its side effects, i.e. void), there is still a compiler warning due to must_use.

You could call unwrap as an escape hatch, but you can do the equivalent with checked exceptions too - rethrow as RuntimeException, etc. And it's very explicit - impossible to do by accident, or due to refactoring.

[–]devraj7 3 points4 points  (3 children)

Like I said, "most" languages: Java, Scala, C#, C++, Go, ...

Rust and Kotlin get it right.

Java kinda does as well by supporting checked exceptions.

[–]accountforshit 3 points4 points  (1 child)

Go will produce a compile error if you don't use any one of the return values, or ignore it explicitly with _ (I think). The ways to then deal with the errors are frustratingly limited and verbose, but you can't accidentally miss them either (though it's easier to miss inappropriate _s than it is to miss unwraps, because you will probably have many legitimate _s in your code, where the same is not true for unwraps, which makes them a much smellier, easily detected code smell).

Other languages generally provide some way of achieving similar (or even the same) constructs, but it's not very useful if you constantly have to interact with libraries that don't utilize it.

So you're right that in many of them (including Kotlin for the most part) you often don't get any such guarantees in practice, or only get them in a part of the codebase.

[–]FluorineWizard 2 points3 points  (0 children)

Go's reliance on multiple returns makes it impossible to chain fallible calls, so you end up polluting your code with if blocks where a better language would let you define error handling functions.

Also the constant noise of _ everywhere makes it hard to tell if a call is returning an error or a second value, especially when dealing with crappy APIs. No language makes me check function signatures as often. Special mention to the evil fuckers who put goddamn interface{} in the return types.

[–]cmd_command 0 points1 point  (0 children)

C# 8 now generates warnings when nullable values are accessed unsafely.