github.com/haraldrudell/parl@v0.4.176/iters/function.go (about) 1 /* 2 © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package iters 7 8 import ( 9 "github.com/haraldrudell/parl/internal/cyclebreaker" 10 "github.com/haraldrudell/parl/perrors" 11 ) 12 13 // Function traverses a function generating values 14 type Function[T any] struct { 15 // IteratorFunction is a function that can be used with function iterator 16 // - if isCancel true, it means this is the last invocation of IteratorFunction and 17 // IteratorFunction should release any resources. 18 // Any returned value is not used 19 // - IteratorFunction signals end of values by returning parl.ErrEndCallbacks. 20 // if hasValue true, the accompanying value is used 21 // - if IteratorFunction returns error, it will not be invoked again. 22 // Any returned value is not used 23 // - IteratorFunction must be thread-safe 24 // - IteratorFunction is invoked by at most one thread at a time 25 iteratorFunction IteratorFunction[T] 26 // BaseIterator implements the DelegateAction[T] function required by 27 // Delegator[T] and Cancel 28 // - provides its delegateAction method to Delegator 29 *BaseIterator[T] 30 } 31 32 // NewFunctionIterator returns an [Iterator] iterating over a function 33 // - thread-safe 34 func NewFunctionIterator[T any]( 35 iteratorFunction IteratorFunction[T], 36 asyncCancel ...func(), 37 ) (iterator Iterator[T]) { 38 if iteratorFunction == nil { 39 panic(cyclebreaker.NilError("iteratorFunction")) 40 } 41 f := &Function[T]{iteratorFunction: iteratorFunction} 42 f.BaseIterator = NewBaseIterator[T](f.iteratorAction, asyncCancel...) 43 return f 44 } 45 46 // Init implements the right-hand side of a short variable declaration in 47 // the init statement for a Go “for” clause 48 // 49 // Usage: 50 // 51 // for i, iterator := NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { 52 // // i is pointer to slice element 53 func (i *Function[T]) Init() (iterationVariable T, iterator Iterator[T]) { 54 iterator = i 55 return 56 } 57 58 // baseIteratorRequest invokes fn recovering a possible panic 59 // - if cancelState == notCanceled, a new value is requested. 60 // Otherwise, iteration cancel is requested 61 // - if err is nil, value is valid and isPanic false. 62 // Otherwise, err is non-nil and isPanic may be set. 63 // value is zero-value 64 // - thread-safe but invocations must be serialized 65 func (i *Function[T]) iteratorAction(isCancel bool) (value T, err error) { 66 // func(isCancel bool) (value T, err error) 67 if value, err = i.iteratorFunction(isCancel); err != nil { 68 err = perrors.Stack(err) 69 } 70 71 return 72 }