Skip to content

Instantly share code, notes, and snippets.

@Hypro999
Last active April 11, 2022 09:23
Show Gist options
  • Save Hypro999/e5fb931a6d0d04f9282daf2cb442e123 to your computer and use it in GitHub Desktop.
Save Hypro999/e5fb931a6d0d04f9282daf2cb442e123 to your computer and use it in GitHub Desktop.
Demonstration of the power of combining generics (introduced in go 1.18) with anonymous functions.
package main
import "fmt"
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
type basicType interface {
int | float64 | bool | string
}
type findableType interface {
basicType | Point
}
func find[T findableType](li []T, check func(T) bool) *T {
for _, v := range(li) {
if check(v) {
return &v
}
}
return nil
}
// You don't always have to use a named type interface, you can
// also use an anonymous one.
func contains[T string | int](li []T, val T) bool {
for _, v := range(li) {
if v == val {
return true
}
}
return false
}
func main() {
points := []Point{
Point{1, 2},
Point{-1, 5},
Point{7, 8},
Point{0, 0},
Point{9, 8},
}
origin := find(points, func(p Point) bool {
if p.x == 0 && p.y == 0 {
return true
}
return false
})
if origin == nil {
fmt.Println("Origin does not exist.")
} else {
fmt.Println("Found an origin.")
}
// You can explicitly specify the type as a "type argument"
// if you'd like:
secondQuadrentValue := find[Point](points, func(p Point) bool {
if p.x < 0 && p.y > 0 {
return true
}
return false
})
if secondQuadrentValue == nil {
fmt.Println("points does not contain a point in the second quadrent.")
} else {
fmt.Printf("Found point in the second quadrent: %v\n", secondQuadrentValue)
}
thirdQuadrentValue := find(points, func(p Point) bool {
if p.x < 0 && p.y < 0 {
return true
}
return false
})
if thirdQuadrentValue == nil {
fmt.Println("points does not contain a point in the third quadrent.")
} else {
fmt.Printf("Found point in the third quadrent: %v.\n", thirdQuadrentValue)
}
names := []string{
"Bob",
"Alice",
"Eve",
}
validNames := []string{
"Bob",
"Alice",
}
findImpostor := func(names []string) *string {
return find(names, func(name string) bool {
return !contains(validNames, name)
})
}
for _, li := range [][]string{names, validNames} {
impostor := findImpostor(li)
if impostor == nil {
fmt.Println("No impostor.")
} else {
fmt.Printf("Impostor: %s.\n", *impostor)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment