Alex

Parametric Polymorphism (Video 42)

// simple generic "map" function
func Map[F, T any](s []F, f func(F) T) []T {
    r := make([]T, len(s))
    for i, v := range s {
        r[i] = f(v)
    }

    return r
}
type Vector[T any] []T

// generic Push function for this new generic vector type
// it takes in a pointer because append() might reallocate, so without 
// a pointer the reallocation would basically just be lost and nothing would result
func (v *Vector[T]) Push(x T) {
    *v = append(*v, x)
}

func main() {
  s := Vector[int]{}
  s.Push(1)
  s.Push(2)

  // using our Map function on the Vector type
  t1 := Map(s, strconv.Itoa)
}

Type Constraints

type StringableVector[T fmt.Stringer] []T // our type T has to conform to the Stringer interface (implement String())

type num int
func (n num) String() {
  return strconv.Itoa(int(n)) // cast our type (this is fine since the underlying type of num is int)
}

func main() {
  var s StringableVector[num] = []num{1,2,3}

  fmt.Println(s)
}