Typically, generics are implemented using either code generation (causing code bloat) or type erasure (which requires boxing the type). They're not satisfied with either.
Typically, generics are implemented using either code generation (causing code bloat) or type erasure (which requires boxing the type). They're not satisfied with either.
Compare:
map f [1, 2, 3]
map g [1.0, 2.0, 3.0]
Versus: integer_map f [1, 2, 3]
double_map g [1.0, 2.0, 3.0]
In both cases, you wind up with specialized versions of map (one for Integers and one for Doubles). The benefit of the generic version is that the programmer must only implement map once, and the compiler handles specializing it for various types. Without generics, the programmer has to write the specialized version for every type he needs the function for. This creates more tedium for the programmer, and does not reduce bloat in any way.Caveat lector: Though my examples above are written in Haskell, I don't have enough knowledge of GHC internals to know whether it performs specialization this way. Nonetheless, it could be a reasonable approach for Go.
Yes, generics will increase compile times. I seriously doubt it will increase compile times by an integer multiple, and most people probably won't even notice.
I'm not entirely sure what's going on that is causing the instruction cache to be underutilized, but it seems to me that the only way to avoid it is to also avoid abstraction in general. As usual, there's a tradeoff between performance and maintainability -- that's nothing new. Pick the appropriate abstractions for your use case.
Russ Cox is wrong in this case because his sample consists of one language: C++. Go is not C++, so it's a mistake to assume it will suffer from the same problems.
To get an idea of how generics could be reasonably implemented, take the Clay programming language as an example: http://claylabs.com/clay/
There is a comprehensive doc by Russ Cox that explains in detail: https://docs.google.com/document/d/1bMwCey-gmqZVTpRax-ESeVuZ...