github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/eval/vals/iterate.go (about)

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