3 ms·
I don't follow go language design very closely, but I'm curious about how this is going to be implemented, if it actually becomes accepted. What comes immediate
by lhorie 6y ago
I don't follow go language design very closely, but I'm curious about how this is going to be implemented, if it actually becomes accepted. What comes immediately to mind is boxing in Java (i.e. you can't have a generic of a primitive).
If go implements generics on top of boxing like Java did, isn't that basically just syntax sugar on top of `type T interface {}`?
For example, today I can write "generic" go code like so:
type T interface {}
func main() {
ints := []T {1,2,3,4}
intsum := Sum(ints, func(a T, b T) T {
return a.(int) + b.(int)
})
fmt.Println(intsum.(int))
}
func Sum(s []T, add func(T, T) T) T {
var sum = s[0]
for i := 1; i < len(s); i++ {
sum = add(sum, s[i])
}
return sum
}
The obvious issue is that the compiler defers type checking to runtime via the type assertions, so it's quite possible to panic on unexpected input; but then again the go compiler doesn't do anything against NPEs either. If the goal is to get the compiler to actually enforce generic types, wouldn't it run into exactly the same sort of problems Java 1.5(?) did in the 90s, or the compiler performance complaints that you get from languages like Rust?
- erik_seaberg 6y agoI believe Go will be monomorphizing Sum[T] and generating machine code for Sum[int](s []int, add func(int, int) int) rather than passing a []interface{} and type checking at runtime (the way Java would for a type-erased sum method). Ada did this, though you had to explicitly instantiate a generic for each type(s) you intended to use (some early C++ compilers also required this).
- lhorie 6y agoProbably a naive question, but couldn't it do the same optimization for the code above? I believe Javascript engines like V8 do something of that sort.
- erik_seaberg 6y agoA []int doesn’t have the same layout in memory as a []interface{}. You could copy the values to a new slice, but that’s expensive and it breaks anything relying on slices being mutable in place (this and covariance vs. contravariance is why Java won’t cast from int[] to Object[]).
- lhorie 6y agoSure, but that's when we think in similar terms to what memory layout C code represents as opposed to what actually gets emitted by gcc -O3. I definitely appreciate being able to mentally visualize what the memory layout of go code looks like, though I'm not sure that's actually an explicit goal of the language.
- kyrra 6y agoMemory layout is something people definitely consider and go. See posts like: https://dave.cheney.net/2015/10/09/padding-is-hard https://dave.cheney.net/2015/10/09/padding-is-hard