'How can I implement a generic filter function?

Suppose I'm implementing this function for filtering a Slice in Golang:

 func Filter(filter func(n int) bool) func(list []int) []int {
   return func(list []int) []int {
     r := make([]int, 0)
     for _, n := range list {
         if filter(n) {
             r = append(r, n)
         }
   }

     return r
 } 
}

To be used like this:

list := []int{1, 4, 3, 2, 7, 4, 9, 7}
r := Filter(func(n int) bool { return n > 3 })(list)

fmt.Println(r)

This works ok, but I have the following questions:

  1. Am I supposed to use the full func syntax instead of a lambda style expression?
  2. If I want my Filter to filter slices of ANY type, what return type should I use?

Thanks!



Solution 1:[1]

  1. As far as I know, no proposal for a more concise anonymous-function notation ("lambda") has been accepted yet.

  2. The addition of type parameters (a.k.a. generics) to the language is planned for early 2022 with the release of Go 1.18. Then, you'll be able to write the program below (playground).

    If you can wait until then, do. At any rate, using the reflect package and peppering one's code with the empty interface{} and type assertions are generally discouraged. One viable alternative until Go 1.18 would be to use go generate to generate the different specializations (for int, string, etc.) you need.

    package main
    
    import "fmt"
    
    func Filter[T any](filter func(n T) bool) func(T []T) []T {
        return func(list []T) []T {
            r := make([]T, 0, len(list))
            for _, n := range list {
                if filter(n) {
                    r = append(r, n)
                }
            }
            return r
        }
    }
    
    func main() {
        list := []int{1, 4, 3, 2, 7, 4, 9, 7}
        r := Filter(func(n int) bool { return n > 3 })(list)
        fmt.Println(r)
    
        list2 := []string{"foo", "bar", "baz", "qux", "quux"}
        r2 := Filter(func(s string) bool { return len(s) <= 3 })(list2)
        fmt.Println(r2)
    }
    

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1