github.com/m4gshm/gollections@v0.0.10/stream/iter.go (about)

     1  // Package stream provides a stream implementation and helper functions
     2  package stream
     3  
     4  import (
     5  	breakLoop "github.com/m4gshm/gollections/break/loop"
     6  	breakStream "github.com/m4gshm/gollections/break/stream"
     7  	"github.com/m4gshm/gollections/c"
     8  	"github.com/m4gshm/gollections/loop"
     9  )
    10  
    11  // New instantiates a stream instance
    12  func New[T any](next func() (T, bool)) Iter[T] {
    13  	return Iter[T]{next: next}
    14  }
    15  
    16  // Iter is the Iterator based stream implementation.
    17  type Iter[T any] struct {
    18  	next func() (T, bool)
    19  }
    20  
    21  var (
    22  	_ Stream[any]                                         = (*Iter[any])(nil)
    23  	_ Stream[any]                                         = Iter[any]{}
    24  	_ loop.Looper[any, Iter[any]]                         = (*Iter[any])(nil)
    25  	_ loop.Looper[any, Iter[any]]                         = Iter[any]{}
    26  	_ c.Filterable[any, Iter[any], breakStream.Iter[any]] = (*Iter[any])(nil)
    27  	_ c.Filterable[any, Iter[any], breakStream.Iter[any]] = Iter[any]{}
    28  	_ c.Iterator[any]                                     = (*Iter[any])(nil)
    29  	_ c.Iterator[any]                                     = Iter[any]{}
    30  	_ c.IterFor[any, Iter[any]]                           = Iter[any]{}
    31  )
    32  
    33  // Next implements c.Iterator
    34  func (t Iter[T]) Next() (element T, ok bool) {
    35  	if next := t.next; next != nil {
    36  		element, ok = next()
    37  	}
    38  	return element, ok
    39  }
    40  
    41  // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function
    42  func (t Iter[T]) Filter(predicate func(T) bool) Iter[T] {
    43  	f := loop.Filter(t.next, predicate)
    44  	return New(f.Next)
    45  }
    46  
    47  // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function
    48  func (t Iter[T]) Filt(predicate func(T) (bool, error)) breakStream.Iter[T] {
    49  	f := breakLoop.Filt(breakLoop.From(t.next), predicate)
    50  	return breakStream.New(f.Next)
    51  }
    52  
    53  // Convert returns a stream that applies the 'converter' function to the collection elements
    54  func (t Iter[T]) Convert(converter func(T) T) Iter[T] {
    55  	conv := loop.Convert(t.next, converter)
    56  	return New(conv.Next)
    57  }
    58  
    59  // Conv returns a breakable stream that applies the 'converter' function to the collection elements
    60  func (t Iter[T]) Conv(converter func(T) (T, error)) breakStream.Iter[T] {
    61  	conv := breakLoop.Conv(breakLoop.From(t.next), converter)
    62  	return breakStream.New(conv.Next)
    63  }
    64  
    65  // ForEach applies the 'walker' function for every element
    66  func (t Iter[T]) ForEach(walker func(T)) {
    67  	loop.ForEach(t.next, walker)
    68  }
    69  
    70  // For applies the 'walker' function for the elements. Return the c.ErrBreak to stop.
    71  func (t Iter[T]) For(walker func(T) error) error {
    72  	return loop.For(t.next, walker)
    73  }
    74  
    75  // Reduce reduces the elements into an one using the 'merge' function
    76  func (t Iter[T]) Reduce(by func(T, T) T) T {
    77  	return loop.Reduce(t.next, by)
    78  }
    79  
    80  // First returns the first element that satisfies the condition of the 'predicate' function
    81  func (t Iter[T]) First(predicate func(T) bool) (T, bool) {
    82  	return loop.First(t.next, predicate)
    83  }
    84  
    85  // Iter creates an iterator and returns as interface
    86  func (t Iter[T]) Iter() c.Iterator[T] {
    87  	return t
    88  }
    89  
    90  // Loop creates an iterator and returns as implementation type reference
    91  func (t Iter[T]) Loop() Iter[T] {
    92  	return t
    93  }
    94  
    95  // Slice collects the elements to a slice
    96  func (t Iter[T]) Slice() []T {
    97  	return loop.Slice(t.next)
    98  }
    99  
   100  // Append collects the elements retrieved by the 'next' function into the specified 'out' slice
   101  func (t Iter[T]) Append(out []T) []T {
   102  	return loop.Append(t.next, out)
   103  }
   104  
   105  // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful
   106  func (t Iter[T]) HasAny(predicate func(T) bool) bool {
   107  	return loop.HasAny(t.next, predicate)
   108  }
   109  
   110  // Start is used with for loop construct like 'for i, val, ok := i.Start(); ok; val, ok = i.Next() { }'
   111  func (t Iter[T]) Start() (Iter[T], T, bool) {
   112  	n, ok := t.next()
   113  	return t, n, ok
   114  }