paths, err := filepath.Glob(dir + "/*.png")
if err != nil {
panic(err)
}
is repeated over and over again.Didn't we learn in the 90's that exceptions are far, far superior to return codes?
paths, err := filepath.Glob(dir + "/*.png")
if err != nil {
panic(err)
}
is repeated over and over again.Didn't we learn in the 90's that exceptions are far, far superior to return codes?
Long answer, the Go authors (Rob Pike et all) have a pedantic issue with exceptions as implemented in Python, Java, etc. They feel they conflate errors and exceptions. Errors, unlike exceptions, are an expected part of the programming process. Exceptions, on the other hand should be for exceptional circumstances.
I did not say that as well as they do so see what Pike has to say about the issue here: http://groups.google.com/group/golang-nuts/browse_thread/thr...
here is an a typical example of the Go community's attitude:
""" I _especially_ don't want exceptions to become an oft-used alternative to multiple levels of error return, as at that point they deteriorate to action at a distance and make understanding large code bases much harder. Been there, done that, got the scars to prove it. (Mostly from C++ and not from Java, but I've seen enough Java to have a healthy fear of runtime exceptions.) """
-- Giles Lean"This is exactly the kind of thing the proposal tries to avoid. Panic and recover are not an exception mechanism as usually defined because the usual approach, which ties exceptions to a control structure, encourages fine-grained exception handling that makes code unreadable in practice. There really is a difference between an error and what we call a panic, and we want that difference to matter. Consider Java, in which opening a file can throw an exception. In my experience few things are less exceptional than failing to open a file, and requiring me to write inside-out code to handle such a quotidian operation feels like a Procrustean imposition.
Our proposal instead ties the handling to a function - a dying function - and thereby, deliberately, makes it harder to use. We want you think of panics as, well, panics! They are rare events that very few functions should ever need to think about. If you want to protect your code, one or two recover calls should do it for the whole program. If you're already worrying about discriminating different kinds of panics, you've lost sight of the ball."
I'm not sure what you mean by "over and over again," in this context, though. There are only three error checks of that kind in this program. It's an unusual program anyway, in that _any_ error condition jumps to the same path: displaying the default image. In most programs you want finer control over error handling than what's shown here.
In my view, all attempts at making a distinction between recoverable and non recoverable errors inevitably fail simply because it is a non local distinction that cannot be made for any particular piece of code in isolation.
// Pseudo Go:
maybe_paths := filepath.Glob(dir + "/*.png")
case maybe_paths of {
Some paths: {
// Do things with paths
}
None: {
// Handle error case
}
}
This makes it impossible to use `paths` if `Glob` returns an error, as `paths` won't be in scope!Furthermore, not having sum types forces us to include a distinguish value `null` for reference (pointer) types, as a way to communicate "no value". This is bad as now we cannot distinguish references that should never be `null` from those than can be `null`.
There is nothing fussy about it, and the only way in which it's at odds with Go's design goals is that Go's design goals include things like "fuck you, only core types get to be generic", "that these mistakes were resolved 20 years ago does not mean we're not going to re-introduce them" and "if we give it a different name it's not the same thing, nah nah nah".
The entire reason Go has multiple return values for functions (such as paths and err in this case) is to avoid having to encode errors in the "real" function result.
Now I agree, that this is less nice as say pattern matching and real sum types, but if you know how to appreciate those just switch to a functional language!
That's nonsense, MRVs are tuples (conceptually, Go implemented them with special syntax because... well, it's Go so it could not go with the general principle now could it?), so Go very specifically encodes errors in the function result.
And using a sum type would encode the error in the type, not in the result itself.
Multiple return values are a special case of tuples. Hence the "conceptually" part.
> Go doesn't have tuples in the type system.
Could you explain how you managed to completely miss the part where I say exactly that?
[1] http://www.gigamonkeys.com/book/beyond-exception-handling-co...
What a great argument, I know better!