github.com/primecitizens/pcz/std@v0.2.1/core/iter/iter.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  
     4  // Package iter.
     5  package iter
     6  
     7  // Core is the minimal interface of an iterator.
     8  //
     9  // Rationales choosing interface over function for iterator definition:
    10  //
    11  //   - Implicit allocations: interface values can use mark.Noescape to avoid
    12  //     allocation but functions cannot, closures always allocate unless
    13  //     properly inlined by the compiler, which is not something controlled
    14  //     by application developers (at the time of go1.21).
    15  //
    16  // Drawbacks of interface:
    17  //
    18  //   - One concrete type can only implement one iterator interface, some types
    19  //     may need multiple iterator implementations.
    20  //     A workaround is to define `type OtherTree Tree` and use pointer type
    21  //     cast for iterator implementation.
    22  type Core[Elem any] interface {
    23  	// Nth returns the n-th element, the returned bool value indicates whether
    24  	// the element exists.
    25  	//
    26  	// It is required to support the 1-step [0, end) range as input sequence,
    27  	// in which case Nth(int) MUST function exactly the same way as Next() would.
    28  	//
    29  	// Caller SHOULD assume the implementation only supports the iteration
    30  	// style implied by the above requirement:
    31  	//
    32  	//	for i := 0; ; i++ {
    33  	//		elem, ok := iter.Nth(i)
    34  	//		if !ok {
    35  	//			break
    36  	//		}
    37  	//
    38  	//		_ = elem
    39  	// 	}
    40  	//
    41  	// Following features are optional:
    42  	//
    43  	//   - Negative n (index from end)
    44  	//   - Step more than 1 (calling with non-consecutive n)
    45  	//   - Backward iteration (calling with n from high to low)
    46  	//   - Arbitrary iteration (calling with unordered n)
    47  	//
    48  	// Rationales choosing Nth(int) instead of Next() as core iterator function:
    49  	//
    50  	//   - Passing an integer argument is cheap (a register in ABIInternal).
    51  	//   - Nth(int) is Next() when called with a sequence of ascending numbers.
    52  	//     (per implementation requirement)
    53  	//   - Nth(int) may skip unwanted elements without extraneous call.
    54  	//   - Nth(int) may step-backward with no external caching.
    55  	//   - Nth(int) is more friendly to slices.
    56  	//   - Nth(int) may be used with binary search to get the total length
    57  	//     of the iterator (when unknown).
    58  	//   - Stateless values can use the integer passed in to decide when to
    59  	//     stop iteration, otherwise an additional Next() style iterator
    60  	//     should be implemented.
    61  	Nth(int) (Elem, bool)
    62  }
    63  
    64  // Func implements Core for function.
    65  type Func[Elem any] func(int) (Elem, bool)
    66  
    67  func (fn Func[Elem]) Nth(i int) (Elem, bool) {
    68  	return fn(i)
    69  }
    70  
    71  // Finite is implemented by iterators with a finite number of elements.
    72  type Finite interface {
    73  	// Len returns the count of elements a iterator may produce.
    74  	Len() int
    75  }
    76  
    77  // Divisible is implemented by iterators can be divided into multiple
    78  // sub-iterators.
    79  type Divisible[Self any] interface {
    80  	// SliceFrom returns a sub-iterator by slicing at the `start` of current
    81  	// itertor, it resembles the native `x[start:]` operation.
    82  	SliceFrom(start int) Self
    83  }
    84  
    85  // Interface is the most complete iterator interface covers most use cases
    86  // of an iterator.
    87  type Interface[T, Self any] interface {
    88  	Core[T]
    89  	Divisible[Self]
    90  	Finite
    91  }
    92  
    93  // CanSkip should be implemented by iterators support skipping elements
    94  // during a single iteration.
    95  //
    96  // Hint: embed iter.MarkCanSkip.
    97  type CanSkip interface {
    98  	IterCanSkip()
    99  }
   100  
   101  // CanBackward should be implemented by iterators support backward iteration
   102  // (from higher to lower).
   103  //
   104  // Hint: embed iter.MarkCanBackward.
   105  type CanBackward interface {
   106  	IterCanBackward()
   107  }
   108  
   109  // CanIndexFromEnd should be implemented by iterators support negative
   110  // argument to Nth(int) method.
   111  //
   112  // Hint: embed iter.MarkCanIndexFromEnd.
   113  type CanIndexFromEnd interface {
   114  	IterCanIndexFromEnd()
   115  }
   116  
   117  // MarkCanSkip is a zero size implementation of CanSkip.
   118  type MarkCanSkip struct{}
   119  
   120  func (MarkCanSkip) IterCanSkip() {}
   121  
   122  // MarkCanBackward is a zero size implementation of CanBackward.
   123  type MarkCanBackward struct{}
   124  
   125  func (MarkCanBackward) IterCanBackward() {}
   126  
   127  // MarkCanIndexFromEnd is a zero size implementation of CanIndexFromEnd.
   128  type MarkCanIndexFromEnd struct{}
   129  
   130  func (MarkCanIndexFromEnd) IterCanIndexFromEnd() {}