4 ms·
The error handling stuff more than lack of generics is my single biggest beef with the language. It is basically C-style error handling from the 80s all over ag
by cromwellian 12y ago
The error handling stuff more than lack of generics is my single biggest beef with the language. It is basically C-style error handling from the 80s all over again, only you return error codes as a separate multi-return value.
The Maybe monad style is so much cleaner, it also allows Elvis operator-like changing, e.g.
foo().getOrElse(blah).getOrElse(baz)
- joelgwebber 12y agoSee my comment above for why I don't find this to be that great for server code. If each of those getOrElse() is an actual potential runtime failure (as opposed to just something that could in theory be nil, but you know won't be, by construction), then it's something you're going to need to deal with explicitly. E.g., think of each of those method calls as being a call to some external system (filesystem, memcache, database, etc) that might fail, even if the code's correct. Throwing an exception is usually a pretty bad strategy for those cases if you want to able to sort out what went wrong later.
- Dewie 12y ago> If each of those getOrElse() is an actual potential runtime failure (as opposed to just something that could in theory be nil, but you know won't be, by construction), then it's something you're going to need to deal with explicitly. getOrElse is a function that is used for exactly that, i.e. for things which can fail in the sense that a parser failed to parse some text because there was a syntax error in the string, or the Map datastructure didn't contain the given key so it returns "nil" or "None" or whatever. If you had something that you know wasn't supposed to be able to fail, then you would probably just go ahead and assume that it can't fail, and let the program error out if it does fail since then you've revealed a bug. To use getOrElse for things that shouldn't fail to begin with is not good. I don't know what you mean by "deal with it explicitly", since getOrElse indeed does deal with it explicitly. > E.g., think of each of those method calls as being a call to some external system (filesystem, memcache, database, etc) that might fail, even if the code's correct. Throwing an exception is usually a pretty bad strategy for those cases if you want to able to sort out what went wrong later. getOrElse doesn't throw an exception. It returns "null" or "None" or whatever value is supposed to represent "does not exist" in the case of some failure (failure here being "produced none/nil/null"). It has nothing to do with throwing (or catching) exceptions.
- joelgwebber 12y agoSorry, I wasn't entirely clear -- I was referring to the original basis for the complaint about verbose error handling. I'm intentionally separating the handling of runtime errors (e.g., memcache request fail) from validation errors (garbage data causes a map to have a nil entry) and unexpected errors (whoops, that shouldn't have been nil). For runtime errors, as I've stated above, I prefer explicit handling close to the error site. I think this is the right tradeoff for server code, though I'm less certain for client code. For validation errors, I prefer, when possible, to have a parser that either succeeds or fails as a whole, and whose output I can then rely upon to be properly constructed. For unexpected nils, I do like the option-type/monad approach, though in most cases (e.g., when writing Go, Java, C++, or Javascript) I just let them NPE/segfault. Note that only one of these cases -- runtime errors -- results in a (result, err) pair in Go. The other two are just about result checking.
- Dewie 12y ago> I'm intentionally separating the handling of runtime errors (e.g., memcache request fail) from validation errors (garbage data causes a map to have a nil entry) and unexpected errors (whoops, that shouldn't have been nil). I think that the original poster (the one you responded to originally) was talking about errors in the first two senses; things that you should/want to handle yourself. I guess the last thing should be handled with a panic? > For unexpected nils, I do like the option-type/monad approach, though in most cases (e.g., when writing Go, Java, C++, or Javascript) I just let them NPE/segfault. It doesn't that you understand idiomatic uses of option-type. Their used for things that legitimately, as a part of the normal operation of the program, can be "null". Not for things that should really not be null. At least I assume that uses of NPE/segfault is not typically used for things that might be null (like returning null from a Map since the value is not there). So, they are not used to "hide" null pointers that shouldn't be null to begin with. For cases where a nullable type, or Option[T] if you will, really should not be null, it would be more idiomatic to "forcefully" extract the value. In other words, use a function that returns the value, or throw an exception if it really isn't a value (it is null); throwing an exception here would be an indication of a bug. But this use is usually thought of as unidiomatic in languages like Haskell: you should rather make sure that you don't have to "forcefully extract" things like that to begin with.