logoalt Hacker News

saghmlast Wednesday at 3:33 AM1 replyview on HN

Because the type named error is used in that flawed way orders of magnitude more than any other type. If there were other types that were consistently used as the last return value in functions that short-cirucuited when calling other functions that retuned specific sentinels in their final value when called, there would be reason to do it for them too.

In fact, this is exactly what Rust's ? -operator already does, and something that's obscured by the oddness of using pseudo-tuples to return errors alongside non-error values rather than requiring exactly one or the other; `Result` in Rust can abstract over any two types (even the same one for success and error, if needed), and using the ?-operator will return the value from the containing function if it's wrapped by `Err` or yield it in the expression if it's wrapped by `Ok`. In Go, the equivalent would be to have the operator work on `(T, E)` where `T` and `E` could be any type, with `E` often but not always being an error. Of course, this runs into the issue of how to deal with more than two return values, but manually wrap the non-error values into a single type in order to use the operator would solve that with overall way less boilerplate than what's required currently due to it being rarely needed.


Replies

9rxlast Wednesday at 5:31 AM

> Because the type named error is used in that flawed way orders of magnitude more than any other type.

That does not give reason to only solve for a narrow case when you can just as well solve for all cases.

> If there were other types that were consistently used as the last return value in functions that short-cirucuited when calling other functions that retuned specific sentinels in their final value when called, there would be reason to do it for them too.

Which is certainly the situation here. (T, bool) is seen as often as (T, error) – where bool is an error state that indicates presence of absence of something. Now that your solution needs to cover "error" and "bool", why not go all the way and include other types too?

Errors are not limited to "error" types. Every value, no matter the type, is potentially an error state. bool is an obvious case, but even things like strings and integers can be errors, depending on business needs. So even if you truly only want to solve for error cases, you still need to be able to accommodate types of every kind.

The computer has no concept of error. It is entirely a human construct, so when handling errors one has to think about from the human perspective or there is no point, and humans decidedly do not neatly place errors in a tightly sealed error box.

> rather than requiring exactly one or the other

That doesn't really make sense in the context of Go. For better or worse, Go is a zero value language, meaning that values always contain useful state. It is necessarily "choose one or the other or both, depending on what fits your situation". "Result" or other monadic-type solutions make sense in other languages with entirely different design ideas, but to try and graft that onto Go requires designing an entirely new language with a completely different notion about how state should be represented. And at that point, what's the point? Just use Rust – or whatever language already thinks about state the way you need.

> but manually wrap the non-error values into a single type in order to use the operator would solve that

I'm not sure that is the case. Even if we were to redesign Go to eliminate zero values to make (T XOR E) sensible, ((T AND U) XOR E) is often not what you want in cases where three or more return arguments are found. (T, bool, error) is a fairly common pattern too, where both bool and error are error states, similar to what was described above. ((T AND U) XOR E) would not fit that case at all. It is more like ((T XOR U) OR (T XOR E)).

I mean, realistically, if we completely reimagined Go to be a brand new language like you imagine then it is apparent that the code written in it would look very different. Architecture is a product of the ecosystem. It is not a foregone conclusion that third return arguments would show up in the first place. But, for the sake of discussion...

show 1 reply