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]