github.com/elves/elvish@v0.15.0/pkg/eval/vals/iterate.go (about) 1 package vals 2 3 // Iterator wraps the Iterate method. 4 type Iterator interface { 5 // Iterate calls the passed function with each value within the receiver. 6 // The iteration is aborted if the function returns false. 7 Iterate(func(v interface{}) bool) 8 } 9 10 type cannotIterate struct{ kind string } 11 12 func (err cannotIterate) Error() string { return "cannot iterate " + err.kind } 13 14 // CanIterate returns whether the value can be iterated. If CanIterate(v) is 15 // true, calling Iterate(v, f) will not result in an error. 16 func CanIterate(v interface{}) bool { 17 switch v.(type) { 18 case Iterator, string, List: 19 return true 20 } 21 return false 22 } 23 24 // Iterate iterates the supplied value, and calls the supplied function in each 25 // of its elements. The function can return false to break the iteration. It is 26 // implemented for the builtin type string, the List type, and types satisfying 27 // the Iterator interface. For these types, it always returns a nil error. For 28 // other types, it doesn't do anything and returns an error. 29 func Iterate(v interface{}, f func(interface{}) bool) error { 30 switch v := v.(type) { 31 case string: 32 for _, r := range v { 33 b := f(string(r)) 34 if !b { 35 break 36 } 37 } 38 case List: 39 for it := v.Iterator(); it.HasElem(); it.Next() { 40 if !f(it.Elem()) { 41 break 42 } 43 } 44 case Iterator: 45 v.Iterate(f) 46 default: 47 return cannotIterate{Kind(v)} 48 } 49 return nil 50 } 51 52 // Collect collects all elements of an iterable value into a slice. 53 func Collect(it interface{}) ([]interface{}, error) { 54 var vs []interface{} 55 if len := Len(it); len >= 0 { 56 vs = make([]interface{}, 0, len) 57 } 58 err := Iterate(it, func(v interface{}) bool { 59 vs = append(vs, v) 60 return true 61 }) 62 return vs, err 63 }