6 ms·
I once had a Go function that, unusually, was _expecting_ an error to be returned from an inner function, and so had to return an error (and do some other proce
by _jab 1y ago
I once had a Go function that, unusually, was _expecting_ an error to be returned from an inner function, and so had to return an error (and do some other processing) if none was returned by the inner function, and return nil if the inner function did return an error.
In a nutshell, this meant I had to do `if err == nil { // return an error }` instead of `if err != nil { ... }`. It sounds simple when I break it down like this, but I accidentally wrote the latter instead of the former, and was apparently so desensitized to the latter construct that it actually took me ages to debug, because my brain simply did not consider that `if err != nil` was not supposed to be there.
I view this as an argument in favor of syntactic sugar for common expressions. Creating more distinction between `if err != nil` (extremely common) and `if err == nil` (quite uncommon) would have been a tangible benefit to me in this case.
- adamrt 1y agoAny time I write "if err == nil" I write // inverted just to make it stick out. It would be nice if it was handled by the language but just wanted to share a way to at least make it a bit more visible. if err == nil { // inverted return err }
- macintux 1y agoI know diddly/squat about Go, but from similar patterns in aeons past, would "nil == err" work as a way to make it stand out?
- haiku2077 1y agoJust tried this and it appears to be valid in the compiler, formatter and golangci-lint
- _whiteCaps_ 1y agohttps://en.wikipedia.org/wiki/Yoda_conditions https://en.wikipedia.org/wiki/Yoda_conditions Works especially well in languages that can make assignments in if statements, e.g: if foo = 42 { }
- macintux 1y agoThank you, I was unaware of this label. Quite descriptive.
- deleted 1y ago[deleted]
- hnlmorg 1y agoI do something similar. I leave a comment but with a short comment why it’s inverted. It’s usually pretty obvious why: eg if err == nil { // we can exit early because we don’t need to keep retrying But it at least saves me having to double check the logic of the code each time I reread the code for the first time in a while.
- vhcr 1y agoWould be nice if code editors colored it differently so it's easier to see.
- prerok 1y agoreturn nil would be clearer, I think. Seems like it's the same but would color differently in my editor.
- School-Cotton 1y agoSomething slightly more elegant (in my subjective opinion) you could do is write if !(err != nil) {
- skybrian 1y agoGood point. Perhaps it could also be solved in an editor with a collapsed notation like ‘if err … {‘
- 9rx 1y agoOf course, `if fruit != "Apple" { ... }` would leave you in the exact same situation. Is there a general solution to improving upon this? Seeing it as an error problem exclusively seems rather misguided. After all, there is nothing special or unique about errors. They're just state like any other.
- adamrt 1y agoI think its more of a comment that "err != nil" is used in the vast majority of cases, so you start to treat it as noise and skim it.
- 9rx 1y agoThat reality may make the fundamental flaws of the if statement more noticeable, but at the end of the day the problem is still that the if statement itself is not great. If we're going to put in effort to improve upon it – and it is fair to say that we should – why only for a type named error?
- saghm 1y agoBecause the type named error is used in that flawed way orders of magnitude more than any other type. If there were other types that were consistently used as the last return value in functions that short-cirucuited when calling other functions that retuned specific sentinels in their final value when called, there would be reason to do it for them too. In fact, this is exactly what Rust's ? -operator already does, and something that's obscured by the oddness of using pseudo-tuples to return errors alongside non-error values rather than requiring exactly one or the other; `Result` in Rust can abstract over any two types (even the same one for success and error, if needed), and using the ?-operator will return the value from the containing function if it's wrapped by `Err` or yield it in the expression if it's wrapped by `Ok`. In Go, the equivalent would be to have the operator work on `(T, E)` where `T` and `E` could be any type, with `E` often but not always being an error. Of course, this runs into the issue of how to deal with more than two return values, but manually wrap the non-error values into a single type in order to use the operator would solve that with overall way less boilerplate than what's required currently due to it being rarely needed.
- derefr 1y agoJust as a devil's-advocate argument, an IDE + font could syntax-highlight + ligature `if err != nil` (only under Golang syntax mode) into a single compact heiroglyph and fade it into the background — which would in turn make anything that differs from that exact string (like `if err == nil`) now pop out, due to not being rendered that way.
- saghm 1y agoThe same logic could apply to the oppositions they cited to the `try` function though; an editor could easily make it stick out to alleviate it blending in when nested inside blocks. This is exactly why nobody ever accidentally confuses `.await` in Rust for a struct field even though from a plaintext perspective it's syntactically identical. If you're going to utilize the editor to carry the heavy weight, you might as well just pick literally any new syntax that replaces all of the extra typing with something more terse.
- purpleidea 1y agoThis is actually an argument against the syntactic changes. Because now if you have the common `if err == nil { return ... }` pattern, then you have _that_ "littering" your code, instead of the syntax. The current solution is fine, and it seems to be only junior/new to golang people who hate it. Everyone I know loves the explicit, clear, easy to read "verbose" error handling.
- scubbo 1y ago> then you have _that_ "littering" your code, instead of the syntax. Yes, exactly. The unusual thing _should_ look unusual.
- 9rx 1y agoThe unusual case does look unusual. == and != are visually very different. I suspect the real problem here is that the parent commenter forgot (read: purposefully avoided) to write tests and is blaming the tools to drown his sorrow.
- scubbo 1y agohttps://news.ycombinator.com/item?id=44172285 https://news.ycombinator.com/item?id=44172285 > [I] was apparently so desensitized to the latter construct that it actually took me ages to debug, because my brain simply did not consider that `if err != nil` was not supposed to be there. Clearly not different enough. Tests are just one tool among many that we use to build and evaluate mental models of behaviour. It's equally possible that the parent commenter noticed unusual behaviour _via_ their tests, and took "ages to debug" precisely _because_ they were misreading the code while trying to understand _why_ the tests were failing. A hypothetical syntax highlighter that flagged up to them "hey, you're doing something unusual here - is that intended?" would have helped them in debugging _alongside_ tests.
- 9rx 1y ago> Clearly not different enough. If you take the word as gospel, but why should we? It is hard to believe. As shocking as it may be, not everything you read on the internet is true. Either way, the fact of the matter is that discussion about code is silly without code. Since I have no knowledge of the actual code in question, which has suspiciously been kept a secret for some reason, I'll open the bidding with this: https://go.dev/play/p/xEnGTmJ_57g https://go.dev/play/p/xEnGTmJ_57g — From the output alone, you don't think you'd be able to gain a pretty good idea of what the problem might be? Feel free to update the code with something more real-worldy if you think the contrivedness of it masks what you are trying to talk about. We had to start somewhere.
- matthewmueller 1y agoI like nil == err for this case
- TZubiri 1y agoNothingburger here, you had a bug, and you fixed it. All is well, no need to question your language or the meaning of life. When you make a mistake irl or trip over when walking, do you reconsider you DNA and submit a patch to God? Sometimes you just gotta have faith in the language and assume it like an axiom, to avoid wasting energy fighting windmills. I'm not a deep Go programmer, but I really enjoy how it's highly resistant to change and consistent across it's 15 years so far.