One of the things I have been looking forward to with Go 1.18's generics is to use a 3-element vector type which can take float32 or float64 for its elements. Come today, this is now possible:
import "golang.org/x/exp/constraints"
type Vec3[T constraints.Float] [3]T
func (vec Vec3[T]) Add(other Vec3[T]) Vec3[T] {
return Vec3[T]{vec[0] + other[0], vec[1] + other[1], vec[2] + other[2]}
}
func (vec Vec3[T]) Mul(factor T) Vec3[T] {
return Vec3[T]{vec[0] * factor, vec[1] * factor, vec[2] * factor}
}
I then wonder, what would an according constraint look like? Omitting the methods, I arrive at the following solution:
type Vec3ish[T constraints.Float] interface {
~[3]T
}
A function taking according arguments could look like so:
func addVecs[A Vec3ish[T], T constraints.Float](a, b A) A {
return A{a[0] + b[0], a[1] + b[1], a[2] + b[2]}
}
This seems verbose. Is it really necessary to define both T and A?
Things get worse when we demand Add and Mul to be implemented:
type Vec3ish[T constraints.Float] interface {
~[3]T
}
type Vec3ishUseful[T constraints.Float, A Vec3ish[T]] interface {
Vec3ish[T]
Add(A) A
Mul(T) A
}
func addVecsGeneric[U Vec3ishUseful[T, A], A Vec3ish[T], T constraints.Float](a U, b A) A {
return a.Add(b)
}
An extra type, three generic type parameters, and having to give a and b separate types. Going further, I see no way to get the expression a.Add(b).Add(b.Add(a)) to work within the function. This isn't the future I was hoping for. What needs to happen here?