4 ms·
I think I know what this trend is, more generally. It has to do with how explicit our code is. We've been through an era where you have some very powerful and c
by zubat 10y ago
I think I know what this trend is, more generally. It has to do with how explicit our code is. We've been through an era where you have some very powerful and compact indirection constructs(event callbacks, polymorphic objects, dynamic types, exceptions) in common parlance and the trend has turned against these lately. Their utility in many instances is mostly to enable technical debt, by worrying about the edge case later, and this has scared a generation of coders who have seen it go astray too often and create code that is hard to usefully refactor. And while exceptions aren't at the center of that trend, they're often implicated as a contributor.
With the new trend, you pay up front and go verbose, put more logic at the call site instead of indirecting it away. Go is at the leading edge of that: lots of LOC for boilerplate is OK in Go-land.
I'm more pragmatic with my error handing methods: I mostly care about whether I can eliminate a class of errors altogether, and secondarily what debugging implications are presented. I don't have a strong opinion on verbosity although I have followed the trend in that respect towards more call site logic.
- quotemstr 10y agoThis trend represents the unlearning of very hard earned lessons. Personally, I can't wait until people rediscover that programming can be more fun and productive without boilerplate. A language being explicit, by itself, is not a feature. Being explicit instead of implicit is only worthwhile if you get clarity in exchange, and boilerplate is clarity-reducing because it's so regular and so obscures program logic.
- burntsushi 10y agoIn Rust, in the common case, the boiler plate you're talking about here is literally a single sigil. (Previously, it was `try!(...)`.) This is of course to say nothing about the advantages of having something that signals "this operation can return an error," (at the call site) but you seem to dismiss that out-of-hand.
- quotemstr 10y agoI do dismiss this advantage out of hand: almost everything can fail, because most things allocate memory. It's only because Rust treats memory specially (incorrectly --- memory is just another resource) that it doesn't appear that more functions can fail. It's much more valuable to flip the sense of the annotation and mark the few functions that cannot fail in any way. Allowing most code to throw just reflects reality and allows you to stop obscuring your program logic with mechanical error handling plumbing. All you do with "try!" is annoy readers by constantly reminding them that things can go wrong when the default assumption should be that things can go wrong.
- burntsushi 10y ago> It's only because Rust treats memory specially (incorrectly --- memory is just another resource) Which is a perfectly reasonable trade off to make. Of course, it's not always the right trade off, so we're looking to improve our story there. If you can't acknowledge that there are real trade offs at play here, then I don't really see how it's possible to meaningfully understand your position (or have a non-frustrating conversation).
- saurik 10y ago(I just want to tell you somewhere that you are not alone, and that I appreciate the time you are taking to have this conversation. The arguments you are making are the exact same things I am often found saying, and in my experience it takes hours of time alone in front of a blackboard with someone to really get them to understand concept like "everything can fail" and "memory is no different than disk space". The one thing I haven't seen you argue with yet is that functions which are adamant they can't fail today often find themselves in a position where they can fail tomorrow, such as by adding authentication or storage; this makes "explicit" error handling a limiting contract that either requires you to proactively return error codes from everything even when they only currently return Success, never extend the functionality of existing systems to avoid accumulating an error condition, be prepared to break that contract in the future, or fall back really really hard on panic.)
- leshow 10y agoGo is more verbose because it lacks a type system that allows generic programming, that seems like a very different kind of verbosity, than explicit error handling IMO. Correct me if I'm wrong, but I don't believe Go's type system enforces you check and handle errors either, so it's not really enforcing verbosity where it counts.
- burntsushi 10y ago> Correct me if I'm wrong, but I don't believe Go's type system enforces you check and handle errors either Go's type system doesn't, but the compiler will in a good number of cases. For example, this will produce a compile time error: value, err := Foo() fmt.Println(value) It produces an error because `err` was declared and unused. The following defeats this check though: value, _ := Foo() // Bar returns one value: an error _ = Bar() Bar() The above list probably isn't exhaustive.