I don't think that's very unique in itself, although Go's particular quirks might be.
I don't think that's very unique in itself, although Go's particular quirks might be.
In those cases, errors are even more like normal values because they're returned using generic types (Optional/Maybe, Result/Either), not using hacky multiple return stuff.
For example, in go you might have a function that returns (string, error), but you can't define a method on that type that was returned, so e.g. you can't have:
func (tuple (string, error)) OrElse(val string) string {
if tuple.1 == nil {
return tuple.0
} else {
return val
}
}
This would let you right such code as: hostname := os.Hostname().OrElse("localhost")
On the other hand, in rust or haskell you'd return a generic sum type which is either an error or a value and which can be treated as an actually normal value.This leads to the languages I mentioned above having the ability to have much cleaner and more concise error handling than go.
The fact that go has multiple returns, not tuples or sum types, results in its errors being really awkward to use values, among their other flaws.
> hostname := os.Hostname().OrElse("localhost")
You could do the following: type maybeString struct {
val string
err error
}
func MaybeString(val string, err error) maybeString {
return maybeString{val, err}
}
func (m maybeString) OrElse(defaultValue string) string {
//...as above...
}
Then you can do: hostname := MaybeString(os.Hostname()).OrElse("localhost")
Of course, this is not practical on a large scale since you don't have generic types and thus would need to `go generate` one instance of the above for each MaybeXXX type. At this point, you're probably better off just writing hostname, err := os.Hostname()
if err != nil {
hostname = "localhost"
}(Both Bash and Perl would very likely have the same syntax as Go if they had tuples.)