Go

Write generic Map, Filter and Reduce for slices. Why aren't they in the standard library's slices package?

Question 136MediumGo 1.22 to 1.25
func Map[T, U any](xs []T, f func(T) U) []U {
    out := make([]U, len(xs))
    for i, x := range xs {
        out[i] = f(x)
    }
    return out
}

func Filter[S ~[]E, E any](xs S, keep func(E) bool) S {
    var out S
    for _, x := range xs {
        if keep(x) {
            out = append(out, x)
        }
    }
    return out
}

func Reduce[T, A any](xs []T, init A, f func(A, T) A) A {
    acc := init
    for _, x := range xs {
        acc = f(acc, x)
    }
    return acc
}

nums := []int{1, 2, 3, 4}
evens := Filter(nums, func(n int) bool { return n%2 == 0 })
strs := Map(evens, strconv.Itoa)
total := Reduce(nums, 0, func(a, n int) int { return a + n })
fmt.Println(strs, total) // [2 4] 10

Why the Go team left them out:

  • A plain for loop is usually clearer.
  • Each step allocates an intermediate slice, whereas a loop fuses the work.
  • Without generic methods you cannot chain fluently, so nested calls read inside-out.
  • Go 1.23 iterators (iter.Seq) are the preferred building block for lazy, fused pipelines. The standard library has slices.Collect, slices.Values and maps.Keys, but deliberately has no Map or Filter.

Note that Filter uses S ~[]E to keep the caller's named type. An in-place variant can reuse xs[:0], which is what slices.DeleteFunc does.

More on Generics

All 36 Generics questions