3 ms·
My understanding of the trade-offs have to do with primarily with devil-in-the-details stuff, i.e. how the feature actually gets implemented. AFAIK, there are
by lhorie 6y ago
My understanding of the trade-offs have to do with primarily with devil-in-the-details stuff, i.e. how the feature actually gets implemented.
AFAIK, there are two major philosophies: implement boxed types (which Go kinda already has, via `interface {}` being implemented as tuple of (type, value), or very aggressive static analysis (like Rust).
The problem with the former is what you get in Java: can't make generics of primitives, and runtime perf issues with boxing/unboxing when you want to e.g. sort terabytes worth of ints.
Conversely, the problem w/ the Rust approach is that the cost is shifted over to the compiler, which has to figure out how to emit optimal primitive-handling code given that the entry point of a generic call tree might be very far away (or even unknown at compile time). This leads to slow compilation times.
For go specifically, I think there's some amount of worry wrt overlapping features (given how go does interfaces) and the subsequent loss of clarity, given that go falls closer to the one-way-of-doing-things side of the scale.
All of these concerns are of the death-by-thousand-paper-cuts variety: can I live with a bit slower compilation times? Yes. Until it's so slow that I can't. Will I love generic collections? Yes. Until I'm neck-deep in a J2EE-like over-architected mess. Etc. Recall that go comes from Google, where minimizing the amount of crap in a billion LOC codebase is considered very important, so concerns like trading off simplicity and compiler speed for other benefits tend to be thought in terms of how the negatives look in the absolute worst case scenario.
- Jtsummers 6y agoMy Go is very rusty so I was spending some time refreshing my memory on the empty interface. As I understand it, in the worst case that Go's generics are implemented with boxed types and a pretty wrapper around the empty interface, you end up with equivalent performance to today but with clearer code (within functions, function declarations becoming somewhat more complicated but not excessively so). But in the best case, this information being given to the compiler will give you clearer code (same qualifications as previous paragraph) and better performance as run-time type verification is moved to compile-time. I suppose if you never use the existing workaround (empty interfaces), then there's no benefit to you in having generics available. But if you do, it seems to me that you're going to get some benefit.
- lhorie 6y agoWell, I don't think the feedback of people that don't use (or, more specifically, who don't feel the pain of not having) generics is all that relevant. In my mind, the trade-off is between potential runtime performance improvements via monomorphization vs the compile time cost of figuring out how to emit said code. I also think there's an important consideration in terms of community and ecosystem. There are plenty of examples elsewhere where splitting on some core aspect of a language had some long lasting damaging effects (python 2 vs 3, perl vs raku, D v1 phobos vs tango, etc). I don't necessarily anticipate that this would be the case here, but it'd be unfortunate if the community split into different go flavors based on similar-but-incompatible ways of doing similar types of tasks.