4 ms·
1. Native enums - yes. 2. Nil - no. > The way I see it, there is a simple solution staring us in the face — make nil a placeholder for the zero value for any
by andreygrehov 5y ago
1. Native enums - yes.
2. Nil - no.
> The way I see it, there is a simple solution staring us in the face — make nil a placeholder for the zero value for any type. [...] Sure, it might be a little odd to see nil used in place of 0 for integer values, but I think this is a small price to pay [...]
So is writing `return MyLongTypeName{}, errors.New("...")`. The power of Go is its explicitness. It's a slippery road to introduce an unintended behavior. The existing use cases for nil are extremely clear. There is no need to change that. I agree that it's annoying to write `return MyLongTypeName{}, errors.New("...")`, but it gives you a chance to think about a better name of a struct and normalize errors. Suddenly, an ugly looking line of code becomes short and nice `return Type{}, ErrInvalidOp`. Maybe Go would benefit from a reserved keyword that would represent a default value of a type, eg
return default, ErrInvalidOp
var x int = default
var y string = default
but again, this is just a syntactic sugar and it may introduce uglier code when used in conjunction with explicit values:
return default, ErrInvalidOp
...
return 0, ErrInvalidOp
// was it intentional to write 0 here? can it be replaced with default? is there a difference between 0 and default?
3. Concise error handling - no
What if you have more than two return values?
func Foo(x int) (int, error, error)
y := Foo(x)?
Which error is being checked, the second or the third one? What if the second is nil, but the third one is not? Anyways, concise error handling has already been discussed by the community million times. Nobody can suggest good solution. When that happens, the best solution is to leave things alone, because, well, doing nothing is also a solution.
- masklinn 5y ago> Native enums - yes. I feel it’d be easier to have “sealed interfaces”: Go already has type switches, so the only missing pieces are defining sealing and adding match completeness support to type switches. > The power of Go is its explicitness. And yet it’s got plenty of implicitness. Though I guess you’re fight in that most of them are footguns? > 3. Concise error handling - no Then you don’t use concise error handling? Seems pretty easy.
- masklinn 5y ago> you’re fight right, obviously.
- denysvitali 5y agoUsually (*SomeType, error) is the most known pattern in Go functions. Having a ? operator that avoids the `if err { return nil, err }` would be awesome. The case you are representing is a clear "anti-pattern" in Go IMHO. Why should a function return two errors? In any case, the ? operator could simply not be applied in this case.
- andreygrehov 5y agoI'm well aware of Go patterns. That is not the point. The point is that the language allows you to return as many values as you want, in any order, of any type. If you introduce a new operator, then that operator should not be driven by a community pattern, but a strict language specification that covers all the use cases allowed by a language. It should also explain how an operator behaves in weird scenarios (eg return err, Type{} vs return Type{}, err). It can surely be all explained by the spec, but Go is the language that wants to minimize "weird scenarios". The best operator is the one that doesn't need explanation. > the ? operator could simply not be applied in this case. No. Go doesn't want to have such operators exist at all, because they are not simple. Go wants to find the most common denominator that would elegantly solve an issue from all angles in such a way so that the authors don't have to write pages of specification, but most importantly, so that code readers don't have to read specification when glancing through code.
- aaomidi 5y agoWhy would you return two error types? Please no
- a_t48 5y agoNot saying this is a good idea or a bad idea - but I could see the use in a function that could both error from a bad file or a dropped network function. You don't really want to combine those two into one enum or error class, but maybe your programming language has support for marking the types of errors a function can return and ensuring coverage.
- mutatio 5y agoCouldn't you wrap errors for that case, accumulate error values or even your own specialised error type?
- a_t48 5y agoSure! Though some of these solutions are pretty opaque to the compiler.
- jpgvm 5y agoWe tried that already, checked exceptions in Java. It wasn't good.
- _flux 5y agoI think one big reason why checked exceptions failed was due to the other big lacking thing: generics. Of course, nowadays Java does have generics but I haven't used Java since then. But in principle with generics and possibly some other additions you could provide much more useful checked exception types: ones that are applicable to your situation and would allow you to bubble up more precise checked exceptions.
- masklinn 5y agoIn reality generics made checked exceptions a lot worse because while you can be generic over checked exceptions you can’t be generic over their combinations, do you can not have a wrapper which is “transparent” to exceptions (e.g. swift’s “rethrows”). You need a wrapper for 0 exceptions, a wrapper for 1, a wrapper for 2, …
- viraptor 5y ago> What if you have more than two return values? You could have a `?` macro which only handles the standard case of two values. If you have more than one, then likely you need to handle it in a specific way anyway. Having `?` does not mean the previous way of checking error doesn't work anymore.