2018-02-15 17:14:05 +08:00
|
|
|
package vals
|
2018-01-25 08:48:31 +08:00
|
|
|
|
|
|
|
// Iterator wraps the Iterate method.
|
|
|
|
type Iterator interface {
|
|
|
|
// Iterate calls the passed function with each value within the receiver.
|
|
|
|
// The iteration is aborted if the function returns false.
|
2022-03-20 23:50:25 +08:00
|
|
|
Iterate(func(v any) bool)
|
2018-01-25 08:48:31 +08:00
|
|
|
}
|
|
|
|
|
2020-01-07 07:02:26 +08:00
|
|
|
type cannotIterate struct{ kind string }
|
|
|
|
|
|
|
|
func (err cannotIterate) Error() string { return "cannot iterate " + err.kind }
|
|
|
|
|
2018-09-28 05:19:47 +08:00
|
|
|
// CanIterate returns whether the value can be iterated. If CanIterate(v) is
|
|
|
|
// true, calling Iterate(v, f) will not result in an error.
|
2022-03-20 23:50:25 +08:00
|
|
|
func CanIterate(v any) bool {
|
2018-09-28 05:19:47 +08:00
|
|
|
switch v.(type) {
|
2019-04-19 19:24:45 +08:00
|
|
|
case Iterator, string, List:
|
2018-09-28 05:19:47 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
// Iterate iterates the supplied value, and calls the supplied function in each
|
|
|
|
// of its elements. The function can return false to break the iteration. It is
|
2019-04-19 19:24:45 +08:00
|
|
|
// implemented for the builtin type string, the List type, and types satisfying
|
|
|
|
// the Iterator interface. For these types, it always returns a nil error. For
|
|
|
|
// other types, it doesn't do anything and returns an error.
|
2022-03-20 23:50:25 +08:00
|
|
|
func Iterate(v any, f func(any) bool) error {
|
2018-01-25 08:48:31 +08:00
|
|
|
switch v := v.(type) {
|
2018-01-25 09:40:15 +08:00
|
|
|
case string:
|
|
|
|
for _, r := range v {
|
|
|
|
b := f(string(r))
|
|
|
|
if !b {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2019-04-19 19:24:45 +08:00
|
|
|
case List:
|
2018-01-28 01:26:22 +08:00
|
|
|
for it := v.Iterator(); it.HasElem(); it.Next() {
|
|
|
|
if !f(it.Elem()) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2019-04-19 08:03:56 +08:00
|
|
|
case Iterator:
|
|
|
|
v.Iterate(f)
|
2018-01-25 09:40:15 +08:00
|
|
|
default:
|
2020-01-07 07:02:26 +08:00
|
|
|
return cannotIterate{Kind(v)}
|
2018-01-25 08:48:31 +08:00
|
|
|
}
|
2018-02-02 12:42:41 +08:00
|
|
|
return nil
|
2018-01-25 08:48:31 +08:00
|
|
|
}
|
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
// Collect collects all elements of an iterable value into a slice.
|
2022-03-20 23:50:25 +08:00
|
|
|
func Collect(it any) ([]any, error) {
|
|
|
|
var vs []any
|
2018-01-25 08:48:31 +08:00
|
|
|
if len := Len(it); len >= 0 {
|
2022-03-20 23:50:25 +08:00
|
|
|
vs = make([]any, 0, len)
|
2018-01-25 08:48:31 +08:00
|
|
|
}
|
2022-03-20 23:50:25 +08:00
|
|
|
err := Iterate(it, func(v any) bool {
|
2018-01-25 08:48:31 +08:00
|
|
|
vs = append(vs, v)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return vs, err
|
|
|
|
}
|