diff --git a/examples.txt b/examples.txt index c631447..1b315d7 100644 --- a/examples.txt +++ b/examples.txt @@ -42,7 +42,7 @@ Sorting by Functions Panic Defer # Recover -# Collection Functions +Collection Functions # String Functions # String Formatting # Regexs diff --git a/examples/collection-functions/collection-functions.go b/examples/collection-functions/collection-functions.go index b242241..ebc3db3 100644 --- a/examples/collection-functions/collection-functions.go +++ b/examples/collection-functions/collection-functions.go @@ -1,23 +1,47 @@ +// We often need our programs to perform operations on +// collections of data, like selecting all items that +// satisfy a given predicate or mapping all items to a new +// collection with a custom function. + +// In some languages it's idiomatic to use [generic](http://en.wikipedia.org/wiki/Generic_programming) +// data structures and algorithms. Go does not support +// generics; in Go it's common to provide collection +// functions if and when they are specifically needed for +// your program and data types. + +// Here are some example collection functions for slices +// of `strings`. You can use these examples to build your +// own functions. Note that in some cases it may be +// clearest to just inline the collection-manipulating +// code directly, instead of creating and calling a +// helper function. + package main import "strings" import "fmt" -func Index(strs []string, s string) int { - for i, str := range strs { - if s == str { +// Returns the first index of the target string `t`, or +// -1 if no match is found. +func Index(vs []string, t string) int { + for i, v := range vs { + if v == t { return i } } return -1 } -func Include(elems []string, val string) bool { - return Index(elems, val) >= 0 +// Returns `true` iff the target string t is in the +// slice. +func Include(vs []string, t string) bool { + return Index(vs, t) >= 0 } -func Any(elems []string, f func(string) bool) bool { - for _, v := range elems { +// Returns `true` iff the one of the strings in the slice +// satisfies the predicate `f`. +func Any(vs []string, f func(string) bool) bool { + for _, v := range vs { if f(v) { return true } @@ -25,8 +49,10 @@ func Any(elems []string, f func(string) bool) bool { return false } -func All(elems []string, f func(string) bool) bool { - for _, v := range elems { +// Returns `true` iff the all of the strings in the slice +// satisfy the predicate `f`. +func All(vs []string, f func(string) bool) bool { + for _, v := range vs { if !f(v) { return false } @@ -34,6 +60,8 @@ func All(elems []string, f func(string) bool) bool { return true } +// Returns a new slice containing all strings in the +// slice that satisfy the predicate `f`. func Filter(vs []string, f func(string) bool) []string { vsf := make([]string, 0) for _, v := range vs { @@ -44,50 +72,40 @@ func Filter(vs []string, f func(string) bool) []string { return vsf } -func Map(strs []string, f func(string) string) []string { - mapped := make([]string, len(strs)) - for i, v := range strs { - mapped[i] = f(v) +// Returns a new slice containing the results of applying +// the function `f` to each string in the original slice. +func Map(vs []string, f func(string) string) []string { + vsm := make([]string, len(vs)) + for i, v := range vs { + vsm[i] = f(v) } - return mapped + return vsm } func main() { + + // Here we try out our various collection functions. var strs = []string{"peach", "apple", "pear", "plum"} fmt.Println(Index(strs, "pear")) - fmt.Println(Index(strs, "grape")) - fmt.Println() - fmt.Println(Include(strs, "pear")) fmt.Println(Include(strs, "grape")) - fmt.Println() fmt.Println(Any(strs, func(v string) bool { return strings.HasPrefix(v, "p") })) - fmt.Println(Any(strs, func(v string) bool { - return strings.HasPrefix(v, "g") - })) - fmt.Println() fmt.Println(All(strs, func(v string) bool { - return strings.Contains(v, "a") + return strings.HasPrefix(v, "p") })) - fmt.Println(All(strs, func(v string) bool { - return strings.Contains(v, "p") - })) - fmt.Println() fmt.Println(Filter(strs, func(v string) bool { - return strings.Contains(v, "p") + return strings.Contains(v, "e") })) - fmt.Println() - fmt.Println(Map(strs, func(s string) string { - return strings.ToUpper(s) - })) - fmt.Println() + // The above examples all used anonymous functions, + // but you can also use named functions of the correct + // type. + fmt.Println(Map(strs, strings.ToUpper)) + } - -// todo: note no generics diff --git a/examples/collection-functions/collection-functions.sh b/examples/collection-functions/collection-functions.sh new file mode 100644 index 0000000..95dc0ee --- /dev/null +++ b/examples/collection-functions/collection-functions.sh @@ -0,0 +1,7 @@ +$ go run collection-functions.go +2 +false +true +false +[peach apple pear] +[PEACH APPLE PEAR PLUM]