10 ms·
Syntactic sugar makes a big difference as well, e.g. Rust's `?` operator.
by bqmjjx0kac 6y ago
Syntactic sugar makes a big difference as well, e.g. Rust's `?` operator.
- donio 6y agoRelative lack of syntactic sugar is one of Go's best features though.
- jzoch 6y agoI dont think thats true at all. Even the sugar they have is strange: see `go` and `make`. Go has plenty of good features and "lack of ergonomic faculties for common programming idioms in Go" is not one of them.
- morelisp 6y ago`new` is basically syntactic sugar (and I personally rarely use it), but `make` is the only way to dynamically allocate or to pre-allocate slices and maps.
- wagslane 6y agoSimplicity in Go is one of it's most loved features. For the most part, there are fewer ways to do the same thing and I love that.
- gher-shyu3i 6y agoIt's actually only superficial simplicity. There have been good comments on HN about this issue. Just because the language is "simple", it doesn't hide the complexity of reality, and written code ends up being harder and more verbose and more difficult to manage compared to powerful languages.
- philosopher1234 6y agoWith all due respect those comments you’re referencing generally don’t know what they’re talking about. There is a lot hatred on this website for Go, which appears to have more to do with “I don’t understand why it’s designed this way, and I think all good languages should look like lisp/Haskell/rust” than “this design is net negative for developers”. Practical simplicity is all about hiding complexity. Unless you’re building a race car, you don’t need to know the differences between file handling in Linux Mac and windows. It just never comes up. And when it does, it’s possible to peak under the hood. A lot of the criticism of go mistakes “difficult to write” or “not trendy” for “bad design”, and again I assert this is because the critics don’t actually understand what Go is designed for, period.
- stouset 6y agoWith all due respect, I do understand why go was designed the way it was, and I vehemently disagree with those decisions. I used go for years, and with every passing day I grew more and more disenfranchised with the language. GP is right. Eschewing abstractions in a programming language forces users of that language to deal with it themselves on a recurring basis. Millions of lines of if res, err := fn(...); err != nil { return nil, fmt.Errorf("...") } don't help anyone, and only detract from readability which is bar none the most important part of a code base. Sadly, this is one of many symptoms in the language where problems that could have been solved in the language have instead been pushed down to its users to deal with over and over and over.
- philosopher1234 6y agoYou claim to understand the decisions, so I’ll push you on that. Why is go error handling designed the way it is? What are the intended benefits? What are the actual benefits? A follow up, on your abstraction point: why does go eschew abstraction? Intended upside? Actual upside? It’s very clear people in these threads can perceive downsides of some of Go’s decisions, but what about upsides? And further, can you recognize how Go copes with the downsides it’s choices produce?
- philosopher1234 6y agoA lot of the criticism of go is a little bit like a guy who hates New York pizza saying “New York pizza sucks, it’s only 1”. Chicago pizza has 4 more inches which has been state of the art for years” Sure, it’s different, but that doesn’t mean it’s bad, and if your criticism only focuses on one detail and leaves out the whole picture, no kidding you produce a harsh judgement.
- stouset 6y agoFrankly your dismissal of people's legitimate concerns with the language as just uneducated griping by fools is one of the reasons I and so many others avoid it and its community like the plague. I don't know what it is about go, but for some reason it seems impossible to have reasoned—if passionate—disagreement about the language. Any criticisms are hand-waved away as just ranting. Everyone who actually uses it knows that none of these things are real problems. And... what are those real problems, anyway? Can't think of any! I love Rust, but I'm more than happy to dive into its warts and agree with legitimate complaints and concerns. Hell, I love Ruby too and that language is full of questionable decisions. Not only are language designers imperfect, but there's no such thing as a perfect language anyway. Great decisions have downsides, and there's no sense in acting like those downsides don't exist. Why is it that gophers never seem to be willing to admit that their language—like all others—has warts, bad tradeoffs, good tradeoffs with uncomfortable but acceptable downsides, and flat-out mistakes? To any criticism, the response is the same: "you don't understand the design", "go's simplicity is its strength", "I've never needed that feature", etc. Hell, the inventor of `nil` calls it his billion-dollar mistake and someone is in this wider discussion arguing that nil pointer dereferences aren't that big a deal. Where on earth are the gophers that will stand up and say, "Yeah, <X> part of golang sucks. I'd change <Y, Z> if I could. But I still really think it hits the right balance overall." Instead, it's all just regurgitation of the same Kool-Aid.
- tsimionescu 6y agoI don't think I know of a single thing where there are fewer ways of doing something in Go than there are in Java. There are multiple ways to declare a variable, to pass a value to a function, to declare a constant, to create something similar to an enum, to return errors, to check for errors, to handle closing, to synchronize parallel threads of execution, to initialize a struct, to create a list of items. I can probably go on. What are some examples where Go is simpler than Java, other than its current lack of generics which has always been a known-limitation?
- sagichmal 6y agoThere is one way to iterate over things, for any kind of elementwise processing: a `for` loop. There is one way to format your code ;)
- tsimionescu 6y agoThere are still two ways: the C-style for loop and its variants (for initializer; condition; increment) and the range for loop with its variants (iterate by key, by value, or both). There's also the option of writing a recrusive function. Still less than Java's five (do-while, while, C-style for, range for, recursion), to be fair.
- searchableguy 6y agoFor any complex codebase, people will build their own sugar and that may differ in implementation so it depends whether that is a good idea. Subtle differences in similar looking code can trip people and increase complexity. Fortunately, go has a good standard library to compensate for some of it.
- stouset 6y agoWhich is simpler? if (ptr == null) { return nil, fmt.Errorf("bad"); } val := *ptr or let value = ptr? If `?` is unacceptable complexity, how on earth do you deal with functions—or, even worse—control flow keywords?
- sagichmal 6y ago`?` makes code substantially less coherent, not more.
- stouset 6y agoI would love to see some rationale behind this opinion.
- sagichmal 6y agoI think the core of it is the belief that error handling is no less important than "happy path" code. In some domains, this isn't true. In mine, distributed systems, it is. So I don't want to relegate errors to some ghetto, I want them to be front and center, equal to everything else. Another small part is probably how you think about the error values themselves. I almost never want to pass an error to my caller exactly as I receive it, I almost always want to do something to it first, most often decorating it with relevant context and metadata where I receive it. Sometimes, obscuring it, if I don't want to leak implementation details. But ultimately it's about explicitness, obviousness. `?` is easy to miss, and permits method chaining, the outcome of which is incredibly easy to mispredict. And in imperative code, which is the supermajority of all code, `?` gives no meaningful increase in speed-of-reading -- which is a bogus metric, anyway. So for me, strongly net negative.
- stouset 6y ago> I want them to be front and center, equal to everything else. That’s fine, and that’s why the function itself will have a return type of `Result<T, E>` for some meaningful return type T and error type E. Even better, if there’s an error, there is no non-error return value. You can’t accidentally use the zero-valued return half of a tuple (as you can in golang) because it simply isn’t there. Is the important part of error handling having some copy-pasted stanza repeated everywhere? Or is it enforcing that errors are always handled and semantically-undefined return values are never accidentally passed along in the event of an error? > But ultimately it's about explicitness, obviousness. `?` is easy to miss, and permits method chaining, the outcome of which is incredibly easy to mispredict. No, it simply is not. `?` early-aborts the function and returns the result straight away if it’s an error, and unwraps the interior value if not. There is no plausible way for someone to mispredict this behavior, and if there was, it would be no different from golang, since the two constructs are semantically virtually identical. One is simply shorter than the other. `?` is no less explicit than three lines of copy-pasted code and both its existence and behavior are forced due to the function’s return type. > And in imperative code, which is the supermajority of all code, `?` gives no meaningful increase in speed-of-reading -- which is a bogus metric, anyway. Ease of understandability is almost hands-down the most important metric given the ratio of frequency to code being read versus written. And to be completely blunt, it is flatly ridiculous that wrapping every line in nearly-identical error handling code somehow doesn’t impair comprehension. The argument is the same for abstractions like `map`, `select`, `reduce` et al. Intent and behavior of code can be understood at a glance when you remove the minutia of looping, bounds-checking, and indexing and focus on just the operation. And as an added bonus, you remove surface area for potential bugs like off-by-one or fencepost errors. Having nearly identical error-handling everywhere both in theory and in practice obscures the places where something is different. It is hard to notice small differences in largely-identical blocks of visual information—hence the existence of “spot the difference" games—but it is trivial to spot when those differences are large. I genuinely struggle to comprehend how people can have ideas like this when they fly in the face of what little hard evidence we do have about syntactic differences in programming.