4 ms·
Go does indeed use the tedious approach. Rust and Zig have nicer syntax for it. But personally, I prefer even Go's "tedious" approach to (unchecked) exceptions
by dilap 6y ago
Go does indeed use the tedious approach. Rust and Zig have nicer syntax for it.
But personally, I prefer even Go's "tedious" approach to (unchecked) exceptions, simply because it's too easy to miss an error case otherwise.
I also find that knowing where errors occur is important information, so I don't really mind having it add an extra line or two. (But the more minimal Rust/Zig syntax is nicer.)
(This attitude comes from having once worked on a python server application, which involved a lot, "oh shit, that throws" whackamole.)
- flowerlad 6y ago> "oh shit, that throws" whackamole You don't have that problem in languages that support checked exceptions.
- dilap 6y agoAgreed, mostly true. (It's still not as explicit about where your function might exit, but you won't get surprise exceptions, which is way nicer.)
- kibwen 6y agoYou may still have that problem if the language also supports unchecked exceptions.
- ufmace 6y agoI've never seen a language that supported checked exceptions and actually used them consistently for everything. But then that would be kind of awful, because IMO the checked exceptions cases for "I know this will never actually throw, leave me alone" and "This is just a quick script, go ahead and blow up the whole program if this fails" are poor, forcing you to write try catch blocks all over the place. IMO, Rust has a nice approach for being stricter - unwrap. If it's a quick script, throw unwrap everywhere with reckless abandon. For real programs, grep for unwrap and make sure for every one, you really know for sure that it will never fail or that blowing up the whole program if it does is the right move. To convert from one to the other, grep unwrap and actually think about what you want to happen if that line is Err.
- dehrmann 6y agoYou do and you don't. If you're using a Java library written by someone who doesn't believe in checked exceptions in Java, you might be lulled into thinking everything will be fine.
- untog 6y agoPersonally I find the Rust syntax is a nice middle ground. If the function returns a Result, it can throw an error. And unless you provide a From<> implementation you do need to handle the specific error that gets thrown. But if you want things to bubble up cleanly you provide From<> (or use a crate that provides it for you) and it all works wonderfully.
- hombre_fatal 6y agoGo's approach is not great. You can leave off return assignment completely. You can't take a tuple as an argument. It has an amateur approach to how you can't shadow `err`, yet `:=` vs `=` change on whether `err` already exists or if your lhs variable is new. You have to do additional work to get a stack trace, errors are usually just strings. You may be forced to handle some errors (unless you trivially ignore them), but nobody is forced to make decent errors. Most libs don't even think about them, like being forced to handle `throw "something went wrong"`. I like errors as return values (mainly Result<V, E>), but Go's is probably the worst impl I've come across. The reason why it's still productive despite this is because we, as developers, tend to not put much thought in errors anyways, so who cares if it sucks (until we need them).
- JamesSwift 6y agoThe lack of a tuple type is the most frustrating for me, because it means you cant define channels as a type of tuple. You have to go through the boilerplate of defining an option type for every single T channel that you handle.
- cle 6y agoCouldn’t you just use a pointer?
- JamesSwift 6y agoWhen I say 'option type' I actually mean the idiomatic go multiple return `(res, err)`. You can define a function to return that but its not actually a first class T, so you cant define a channel that follows the same semantics. That means if you have a bunch of functions that use the `(res, err)` style and you later want to convert them to, e.g., batch processing steps using channels, you have to now add a lot of boilerplate type definitions to tie things together.
- zem 6y agoeven more annoyingly, you can define a function that returns it but not a function that accepts it, so you often have to jump through a lot of hoops to combine higher order functions with multiple return values.
- dehrmann 6y ago> python server application, which involved a lot, "oh shit, that throws" whackamole. This matches my experiences with Python, and docs, even official Python docs, are somewhat lacking when they describe what might get thrown.