4 ms·
I think I'd want more than multiple return values. I'd also want syntactic sugar to pass errors through to callers, or alternatively, ignore errors and skip fut
by jjnoakes 10y ago
I think I'd want more than multiple return values. I'd also want syntactic sugar to pass errors through to callers, or alternatively, ignore errors and skip future processing and have the error be the result of the future processing.
These things are typically done by exceptions and monads; the "zig" language has some interesting syntax around this kind of thing as well.
But just multiple return values isn't enough for me - too much "if error return error" noise for my taste.
- voidlogic 10y ago>too much "if error return error" noise for my taste. I understand that. I was pointing out this is less noise than try-catch-finally (assuming the programmer is comparing Go to C++/Java/C#). I don't deny some functional langs have more elegant handling in this respect.
- spullara 10y agoIt isn't less noisy. With exceptions I can choose to have no noise or concentrate all the noise in one part of the method. In Go there is junk all over the method deeply conflating the good path and the exceptional path.
- majewsky 10y agoIf you add exceptions, you trade noise for action-at-a-distance. From my experience, I prefer a little noise over action-at-a-distance.
- h1d 10y agoEverything is already at a distance when you load libraries and bundle up your commonly used functions elsewhere. DRY principle seems not applicable here.
- Noughmad 10y agoNo, it's not less noise, because with exceptions, you can put all you error handling in one place, or wherever is the most appropriate. With go, you are forced to handle it at literally every function call. If you want some data, "if err != nil return err" contains the four most frequently used words in Go code. See https://anvaka.github.io/common-words/#?lang=go https://anvaka.github.io/common-words/#?lang=go . For comparion, try/catch are only 34th and 35th for Java, and even lower for C# and C++.
- dragonwriter 10y ago> With go, you are forced to handle it at literally every function call. Every call that can fail, which isn't quite every function call.
- stouset 10y ago> But just multiple return values isn't enough for me - too much "if error return error" noise for my taste. This is such a big deal, I don't understand how it's defensible. Code is read dozens of times more often than it's written. When code looks like: if val1, err := thingImActuallyTryingToDo1(); err != nil { return nil, fmt.Errorf("thing failed: %v", err) } if val2, err := thingImActuallyTryingToDo2(val1); err != nil { return nil, fmt.Errorf("thing failed differntly: %v", err) } if val3, err := thingImActuallyTryingToDo3(val3); err != nil { return nil, fmt.Errorf("thing failed again: %v", err) } it's impossible to tell at a glance how the function is actually working. You have to parse out 90% garbage just to get to the details of what's really happening. Worse is that it's never this "clean" and repeatable in practice. It becomes a bunch of subtly-different variants on that theme (append if the function wasn't an error, or do something different if it errored, etc.) that the actual logic of your function is obscured in a maze of error-handling.
- majewsky 10y ago> it's impossible to tell at a glance how the function is actually working. You have to parse out 90% garbage just to get to the details of what's really happening. After a while, you just learn to ignore the `if err != nil` and get on with your life. I mean, sure, it would still be nicer to have an abbreviation, but it's not like Go code is 90% `if err != nil` (as critics always try to frame), and when I read Go code, I'm most definitely not spending most (or any) of my time stumbling over them.
- prodigal_erik 10y agoIt's not 90%, but it seems like it has to be more than 50% because not only does every call require an error check but f(g(x), h(y)) has to be broken down and given three error checks.
- stouset 10y agoYeah. In my experience it's way closer than 90% than 50%. Even with one argument, function chaining is absurdly annoying. You can't just call f(g(x)), because you have to pull out the error check and do it manually. And most of your code winds up doing error checks because if any call in the stack under a particular function produces an error, it usually winds up having to bubble the entire way up the stack.