4 ms·
I understand that this is true for a lot of application code. It's not true for library authors though, and every language needs libraries.
by fauigerzigerk 2mo ago
I understand that this is true for a lot of application code. It's not true for library authors though, and every language needs libraries.
- hnlmorg 2mo agoI’ve written a lot of libraries too. The problem is generics only solve a very small part of the equation: compile time checks for composite types. But to use composite types in anything non-trivial in Go, you then need reflection. Which is slow. And if you then need reflection, you’re already passing interface types anyway plus you’re back to having to handle type-handling errors in the runtime. So if you’re writing a library that’s expected to have any kind of performance, you’re back to code duplication and having a DoSomethingType() function signatures again. Or you stick with reflection and take that performance hit PLUS the risk of compile time constraints being runtime errors; which is the a lose-lose scenario. And let’s also not forget that reflection can be just as verbose as code duplication, and harder to get right too. Don’t get me wrong, I’m glad we have generics. But people on HN massively overstate the value of them in a AOT non-dynamic, strictly typed language like Go. I guess you could argue that Go has other shortcomings that directly result in generics having limited value. But then you’re basically just arguing that you prefer coding in a different language paradigm, and at that point, you’re much better off using that other paradigm instead of complaining that Go isn’t JavaScript or Haskell.
- pezo1919 2mo agoThanks for that, nicely put, interesting angle.
- theptip 2mo agoInteresting, thanks - is the problem you’re describing solved by Rust’s macros (eg derive) or are there further issues you see even there?
- kccqzy 2mo agoYes it is precisely Go’s shortcomings that would require typical use of generics to also require reflection most of the time. You would want Rust traits (or Haskell type classes) or C++ style type traits and then the need for reflection is much reduced. So Go has painted itself into a corner where generics feel bolted on and less useful than generics in other languages. It’s still Go’s fault and people rightfully argue that they should prefer a different language. The Go language itself is never its strength but it has a good runtime, wonderful standard library and tooling. People never picked Go for being an amazing language, but rather for these other things.
- hnlmorg 2mo agoI picked Go for the language, so your argument is incorrect. Go’s shortcoming is also its strength. Language design is a constant battle of tradeoffs. And I happen to find many of the decisions C++ and Rust made weren’t analogous with my preferences. > It’s still Go’s fault and people rightfully argue that they should prefer a different language. It’s no more Gos fault than it is the people using Go. It’s called an “opinion” and “preference”. Please don’t assuming your preference is some global truth, because it is not.
- foldr 2mo ago>You would want Rust traits Go generics does have this feature. You can require a generic type to implement an interface.
- kccqzy 2mo agoRequiring the implementation of a Go interface is less powerful than requiring a trait. It reminded me of early years of Rust where people saw traits and asked, well Java had interfaces for many decades, what’s the innovation?
- foldr 2mo agoI'm not sure you can really argue that Rust's traits are innovative. Haskell typeclasses, OO-style abstract interfaces, and C++-style associated types were already well-known and well-established features. The particular mix of those features in Rust may be new, but the same could be said for Go's, or really any programming language's, particular mix of features. You're right of course that traits are more powerful than interfaces. Go simply isn't designed to satisfy fans of elaborate type systems. This can be frustrating at times, but it also means that you don't have to deal with overarchitected library code like this: https://github.com/marshallpierce/rust-base64/issues/213 https://github.com/marshallpierce/rust-base64/issues/213 (Yes, you can overarchitect code in Go too, but the simplicity of the language, and the model of the stdlib, do tend to discourage this in practice.) I've never written Rust professionally, but I did have a Haskell job for a couple of years. IME the sophistication of the type system is a double-edged sword. Sometimes it lets you concisely express important invariants; sometimes you end up spending way too much time writing elaborate types for code that isn't really doing anything very interesting. I understand the appeal of fancy type systems. In practice, I get a productivity boost from any kind of basic static typing, and then rapidly diminishing returns from the fancier stuff.