6 ms·
But in Rust you can do the same, I do this all the time: let _ = fs::mkdir_all() // Error ignored, Rust will not complain because you explicitly assigned to
by nulld3v 3y ago
But in Rust you can do the same, I do this all the time:
let _ = fs::mkdir_all() // Error ignored, Rust will not complain because you explicitly assigned to _
Or if the function returns something I need but I don't care about the error:
let Ok(file) = get_file() else {
file_unavailable();
return
}
upload_file(file);
Or this:
let file = get_file().unwrap_or_default()
- randomdata 3y ago[flagged]
- nulld3v 3y agoSo what is the point of the distinction then? The examples I gave were idomatic Rust too. Both Go and Rust hand the caller an error and the caller then must do something with the error. In both Go and Rust, you can assign the error to underscore and ignore it. Java is different but we aren't talking about Java right now. The only difference is that in Go the function can (and must) still provide a value for "file" even when there is an error. In Rust you can kind of do something similar, by giving the File struct a default value (that's what "unwrap_or_default()" is) but it isn't exactly the same. I would argue that such a case is extremely rare though.
- randomdata 3y ago> Both Go and Rust hand the caller an error and the caller then must do something with the error. This is simply not true. Go preaches that values should always be useful. Given a return signature (T, error), the value of type T can be used irrespective of what is contained in the value of type error. They are independent states. > The only difference is that Go provides a value for "file" when there is an error. Yes, that is ultimately the difference. Result takes what are independent states and tries to make them dependent. Result<T, error> assumes that if there is a value of type error then the caller would not make use of the value of type T. Often they will be dependent for all practical purposes. It is not an unreasonable assumption to assume that they are, especially if you know the caller. However, Go believes you cannot make that assumption. That you have to let the caller determine what it finds useful, not what you think it might find useful. Ease of code reusability is clearly a design goal of Go, so the idea that you can't get to know your callers and how they will use your function isn't unwarranted. Tradeoffs, as always.
- awused 3y agoResult covers the very common case where there is T or error but never both. Having a decent type system doesn't prevent you from returning both. In Go I simply cannot have something as simple as "A or B, but never both or neither" as a type. >However, Go believes you cannot make that assumption. This is trying to twist a weakness of Go's type system as a virtue. In Go I always have "A or B, including neither and both". I can have that in Rust or Haskell if I want, but usually I want "A or B, never both or neither" and rarely "A or B, sometimes both but never neither" which Rust and Haskell can do but Go cannot. This comes from Go using product types as a poor replacement for sum types.
- randomdata 3y ago> This is trying to twist a weakness of Go's type system as a virtue. No. There is no discussion about type systems taking place here at all. The discussion is about patterns where the producer or the consumer is in control. Specifically, Result puts the producer in control. Idiomatic Go (T, error) sees the consumer in control. There is likely no language in existence that prevents you from choosing. You can write code where the producer is in control in Go, and you can write code where the consumer is in control in every other. These are not features of a language, although language idioms do often push developers one way or the other.
- awused 3y agoThis entire discussion is about the type system and how it interacts with the language. Go does not have sum types, so the producer cannot signal to the consumer what it can produce and what the consumer has to handle. The consumer in Go must pessimistically assume the all combinations of return values are possible, where in a language with a decent type system the possible cases can be enumerated and handled appropriately. >Idiomatic Go sees the caller in control. This is simply not true. If the producer never returns A+B, then the consumer is never going to magic that into existence. The producer is always in control of what the producer returns. >Specifically, Result puts the producer in control. Result is just a convenience type for the very common case of a function returning "A or B, but never both or neither." If your producer does not match that, you are not forced by the language to use Result. In Go, you are always forced by the language to return a value of type "A or B, including both or neither." The consumer isn't any more in control, it just has to guess whether "both or neither" are possible return types. In Rust/Haskell/Ocaml/Java, hell even C++ with variant or C with union, I can return something or with a more restrictive type. Honestly Go is uniquely incapable of representing these cases in its type system and control flow.