iterate.go 1.6 KB

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