From f5e506106844782348fc03a66070c154dfe339de Mon Sep 17 00:00:00 2001 From: leaxoy Date: Tue, 19 Jul 2022 15:30:11 +0800 Subject: [PATCH] [iterator] expose iterator/internal as iterator/ops for ordinary usage --- iterator/adapters/slice.go | 4 ++ iterator/{internal => ops}/arith.go | 32 ++++-------- iterator/{internal => ops}/bool.go | 16 ++---- iterator/{internal => ops}/chain.go | 2 +- iterator/{internal => ops}/chunk.go | 2 +- iterator/{internal => ops}/clone.go | 2 +- iterator/{internal => ops}/cmp.go | 2 +- iterator/{internal => ops}/collect.go | 2 +- iterator/{internal => ops}/filter.go | 2 +- iterator/{internal => ops}/flatten.go | 2 +- iterator/{internal => ops}/fold.go | 2 +- iterator/{internal => ops}/for_each.go | 2 +- iterator/{internal => ops}/inspect.go | 2 +- iterator/{internal => ops}/map.go | 2 +- iterator/{internal => ops}/reduce.go | 2 +- iterator/stream/impl.go | 71 +++++++++++++++----------- iterator/stream/stream.go | 35 ++++++++++++- 17 files changed, 103 insertions(+), 79 deletions(-) rename iterator/{internal => ops}/arith.go (61%) rename iterator/{internal => ops}/bool.go (81%) rename iterator/{internal => ops}/chain.go (96%) rename iterator/{internal => ops}/chunk.go (97%) rename iterator/{internal => ops}/clone.go (97%) rename iterator/{internal => ops}/cmp.go (96%) rename iterator/{internal => ops}/collect.go (93%) rename iterator/{internal => ops}/filter.go (99%) rename iterator/{internal => ops}/flatten.go (96%) rename iterator/{internal => ops}/fold.go (93%) rename iterator/{internal => ops}/for_each.go (95%) rename iterator/{internal => ops}/inspect.go (98%) rename iterator/{internal => ops}/map.go (96%) rename iterator/{internal => ops}/reduce.go (96%) diff --git a/iterator/adapters/slice.go b/iterator/adapters/slice.go index 57ccf60..8064af8 100644 --- a/iterator/adapters/slice.go +++ b/iterator/adapters/slice.go @@ -19,6 +19,10 @@ func (self *sliceIter[T]) Next() optional.Optional[T] { return optional.None[T]() } +func (self *sliceIter[T]) SizeHint() (uint, optional.Optional[uint]) { + return 0, optional.Some(uint(len(self.elements))) +} + func OfSlice[T any](eles ...T) iterator.Iterator[T] { return &sliceIter[T]{elements: eles} } diff --git a/iterator/internal/arith.go b/iterator/ops/arith.go similarity index 61% rename from iterator/internal/arith.go rename to iterator/ops/arith.go index 0188a10..fcd855b 100644 --- a/iterator/internal/arith.go +++ b/iterator/ops/arith.go @@ -1,27 +1,19 @@ -package internal +package ops import ( "github.com/go-board/std/cmp" + "github.com/go-board/std/cond" + "github.com/go-board/std/core" "github.com/go-board/std/iterator" "github.com/go-board/std/optional" ) func MaxBy[T any](iter iterator.Iterator[T], ord cmp.OrdFunc[T]) optional.Optional[T] { - return Reduce(iter, func(a, b T) T { - if ord(a, b).IsLe() { - return a - } - return b - }) + return Reduce(iter, func(a, b T) T { return cond.Ternary(ord(a, b).IsGe(), a, b) }) } func MinBy[T any](iter iterator.Iterator[T], ord cmp.OrdFunc[T]) optional.Optional[T] { - return Reduce(iter, func(a, b T) T { - if ord(a, b).IsLe() { - return a - } - return b - }) + return Reduce(iter, func(a, b T) T { return cond.Ternary(ord(a, b).IsLe(), a, b) }) } func SumBy[T any](iter iterator.Iterator[T], sum func(T, T) T) optional.Optional[T] { @@ -32,11 +24,7 @@ func ProductBy[T any](iter iterator.Iterator[T], product func(T, T) T) optional. return Reduce(iter, product) } -type Numbric interface { - int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64 -} - -func ord[T Numbric](lhs, rhs T) cmp.Ordering { +func ord[T core.Ordered](lhs, rhs T) cmp.Ordering { if lhs > rhs { return cmp.Greater } else if lhs < rhs { @@ -45,19 +33,19 @@ func ord[T Numbric](lhs, rhs T) cmp.Ordering { return cmp.Equal } -func Max[T Numbric](iter iterator.Iterator[T]) optional.Optional[T] { +func Max[T core.Ordered](iter iterator.Iterator[T]) optional.Optional[T] { return MaxBy(iter, ord[T]) } -func Min[T Numbric](iter iterator.Iterator[T]) optional.Optional[T] { +func Min[T core.Ordered](iter iterator.Iterator[T]) optional.Optional[T] { return MinBy(iter, ord[T]) } -func Sum[T Numbric](iter iterator.Iterator[T]) optional.Optional[T] { +func Sum[T core.Number](iter iterator.Iterator[T]) optional.Optional[T] { return SumBy(iter, func(t1 T, t2 T) T { return t1 + t2 }) } -func Product[T Numbric](iter iterator.Iterator[T]) optional.Optional[T] { +func Product[T core.Number](iter iterator.Iterator[T]) optional.Optional[T] { return ProductBy(iter, func(t1 T, t2 T) T { return t1 * t2 }) } diff --git a/iterator/internal/bool.go b/iterator/ops/bool.go similarity index 81% rename from iterator/internal/bool.go rename to iterator/ops/bool.go index d20e01f..be125f8 100644 --- a/iterator/internal/bool.go +++ b/iterator/ops/bool.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/cmp" @@ -38,21 +38,11 @@ func matchCount[T any](iter iterator.Iterator[T], predicate func(T) bool, n uint } func None[T any](iter iterator.Iterator[T], predicate func(T) bool) bool { - for s := iter.Next(); s.IsSome(); s = iter.Next() { - if predicate(s.Value()) { - return false - } - } - return true + return All(iter, func(t T) bool { return !predicate(t) }) } func ContainsBy[T any](iter iterator.Iterator[T], target T, eq cmp.EqFunc[T]) bool { - for s := iter.Next(); s.IsSome(); s = iter.Next() { - if eq(s.Value(), target) { - return true - } - } - return false + return Any(iter, func(t T) bool { return eq(t, target) }) } func Contains[T comparable](iter iterator.Iterator[T], target T) bool { diff --git a/iterator/internal/chain.go b/iterator/ops/chain.go similarity index 96% rename from iterator/internal/chain.go rename to iterator/ops/chain.go index 2db80f7..ae571ff 100644 --- a/iterator/internal/chain.go +++ b/iterator/ops/chain.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/chunk.go b/iterator/ops/chunk.go similarity index 97% rename from iterator/internal/chunk.go rename to iterator/ops/chunk.go index 6368b96..fe80c37 100644 --- a/iterator/internal/chunk.go +++ b/iterator/ops/chunk.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/clone.go b/iterator/ops/clone.go similarity index 97% rename from iterator/internal/clone.go rename to iterator/ops/clone.go index 3f0ecbf..210408e 100644 --- a/iterator/internal/clone.go +++ b/iterator/ops/clone.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/clone" diff --git a/iterator/internal/cmp.go b/iterator/ops/cmp.go similarity index 96% rename from iterator/internal/cmp.go rename to iterator/ops/cmp.go index ad72952..1c4d07b 100644 --- a/iterator/internal/cmp.go +++ b/iterator/ops/cmp.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/cmp" diff --git a/iterator/internal/collect.go b/iterator/ops/collect.go similarity index 93% rename from iterator/internal/collect.go rename to iterator/ops/collect.go index 4aa338b..6989920 100644 --- a/iterator/internal/collect.go +++ b/iterator/ops/collect.go @@ -1,4 +1,4 @@ -package internal +package ops import "github.com/go-board/std/iterator" diff --git a/iterator/internal/filter.go b/iterator/ops/filter.go similarity index 99% rename from iterator/internal/filter.go rename to iterator/ops/filter.go index 8e3443a..e18c81e 100644 --- a/iterator/internal/filter.go +++ b/iterator/ops/filter.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/flatten.go b/iterator/ops/flatten.go similarity index 96% rename from iterator/internal/flatten.go rename to iterator/ops/flatten.go index d039b1e..6d3fdbd 100644 --- a/iterator/internal/flatten.go +++ b/iterator/ops/flatten.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/fold.go b/iterator/ops/fold.go similarity index 93% rename from iterator/internal/fold.go rename to iterator/ops/fold.go index f907e81..5efd6e3 100644 --- a/iterator/internal/fold.go +++ b/iterator/ops/fold.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/for_each.go b/iterator/ops/for_each.go similarity index 95% rename from iterator/internal/for_each.go rename to iterator/ops/for_each.go index bf14000..f8dd54a 100644 --- a/iterator/internal/for_each.go +++ b/iterator/ops/for_each.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/inspect.go b/iterator/ops/inspect.go similarity index 98% rename from iterator/internal/inspect.go rename to iterator/ops/inspect.go index 925541c..8fb15ab 100644 --- a/iterator/internal/inspect.go +++ b/iterator/ops/inspect.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/map.go b/iterator/ops/map.go similarity index 96% rename from iterator/internal/map.go rename to iterator/ops/map.go index e992a34..ca04165 100644 --- a/iterator/internal/map.go +++ b/iterator/ops/map.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/internal/reduce.go b/iterator/ops/reduce.go similarity index 96% rename from iterator/internal/reduce.go rename to iterator/ops/reduce.go index 5797fff..edbe359 100644 --- a/iterator/internal/reduce.go +++ b/iterator/ops/reduce.go @@ -1,4 +1,4 @@ -package internal +package ops import ( "github.com/go-board/std/iterator" diff --git a/iterator/stream/impl.go b/iterator/stream/impl.go index 3245e99..9b4efa4 100644 --- a/iterator/stream/impl.go +++ b/iterator/stream/impl.go @@ -3,20 +3,20 @@ package stream import ( "github.com/go-board/std/cmp" "github.com/go-board/std/iterator" - "github.com/go-board/std/iterator/internal" + "github.com/go-board/std/iterator/ops" "github.com/go-board/std/optional" ) -type streamImpl[T any] struct { - iter iterator.Iterator[T] -} +type streamImpl[T any] struct{ iter iterator.Iterator[T] } var _ Stream[any] = (*streamImpl[any])(nil) +// FromIterator returns a Stream[T] from an iterator.Iterator[T]. func FromIterator[T any](iter iterator.Iterator[T]) Stream[T] { return &streamImpl[T]{iter: iter} } +// FromIterable returns a Stream[T] from an iterator.Iterable[T]. func FromIterable[T any](iterable iterator.Iterable[T]) Stream[T] { return FromIterator(iterable.Iter()) } @@ -24,98 +24,109 @@ func FromIterable[T any](iterable iterator.Iterable[T]) Stream[T] { func (self *streamImpl[T]) Iter() iterator.Iterator[T] { return self.iter } func (self *streamImpl[T]) All(predicate func(T) bool) bool { - return internal.All(self.iter, predicate) + return ops.All(self.iter, predicate) } func (self *streamImpl[T]) Any(predicate func(T) bool) bool { - return internal.Any(self.iter, predicate) + return ops.Any(self.iter, predicate) } func (self *streamImpl[T]) Once(predicate func(T) bool) bool { - return internal.Once(self.iter, predicate) + return ops.Once(self.iter, predicate) } func (self *streamImpl[T]) None(predicate func(T) bool) bool { - return internal.None(self.iter, predicate) + return ops.None(self.iter, predicate) } func (self *streamImpl[T]) Chain(o iterator.Iterable[T]) Stream[T] { - return &streamImpl[T]{iter: internal.Chain[T](self.iter, o)} + return &streamImpl[T]{iter: ops.Chain[T](self.iter, o)} } func (self *streamImpl[T]) Map(transformer func(T) T) Stream[T] { - - return &streamImpl[T]{iter: internal.Map(self.iter, transformer)} + return &streamImpl[T]{iter: ops.Map(self.iter, transformer)} } func (self *streamImpl[T]) Filter(predicate func(T) bool) Stream[T] { - return &streamImpl[T]{iter: internal.Filter(self.iter, predicate)} + return &streamImpl[T]{iter: ops.Filter(self.iter, predicate)} +} + +func (self *streamImpl[T]) Fold(initial T, accumulator func(T, T) T) T { + return ops.Fold(self.iter, initial, accumulator) } func (self *streamImpl[T]) Reduce(reduce func(T, T) T) optional.Optional[T] { - return internal.Reduce(self.iter, reduce) + return ops.Reduce(self.iter, reduce) } func (self *streamImpl[T]) Flatten(flatten func(T) iterator.Iterator[T]) Stream[T] { - return &streamImpl[T]{iter: internal.Flatten(self.iter, flatten)} + return &streamImpl[T]{iter: ops.Flatten(self.iter, flatten)} +} + +func (self *streamImpl[T]) Chunk(size int) Stream[Stream[T]] { + panic("implement me") } func (self *streamImpl[T]) Inspect(inspect func(T)) Stream[T] { - return &streamImpl[T]{iter: internal.Inspect(self.iter, inspect)} + return &streamImpl[T]{iter: ops.Inspect(self.iter, inspect)} } func (self *streamImpl[T]) MaxBy(ord cmp.OrdFunc[T]) optional.Optional[T] { - return internal.MaxBy(self.iter, ord) + return ops.MaxBy(self.iter, ord) } func (self *streamImpl[T]) MinBy(ord cmp.OrdFunc[T]) optional.Optional[T] { - return internal.MinBy(self.iter, ord) + return ops.MinBy(self.iter, ord) } -func (self *streamImpl[T]) Equal(o iterator.Iterable[T], ord cmp.EqFunc[T]) bool { - return internal.EqualBy(self.iter, o, ord) +func (self *streamImpl[T]) EqualBy(o iterator.Iterable[T], ord cmp.EqFunc[T]) bool { + return ops.EqualBy(self.iter, o, ord) } func (self *streamImpl[T]) Collect() []T { - return internal.Collect(self.iter) + return ops.Collect(self.iter) } func (self *streamImpl[T]) Nth(n uint) optional.Optional[T] { - return internal.Nth(self.iter, n) + return ops.Nth(self.iter, n) } func (self *streamImpl[T]) Take(n uint) Stream[T] { - return &streamImpl[T]{iter: internal.Take(self.iter, n)} + return &streamImpl[T]{iter: ops.Take(self.iter, n)} } func (self *streamImpl[T]) Skip(n uint) Stream[T] { - return &streamImpl[T]{iter: internal.Skip(self.iter, n)} + return &streamImpl[T]{iter: ops.Skip(self.iter, n)} } func (self *streamImpl[T]) TakeWhile(predicate func(T) bool) Stream[T] { - return &streamImpl[T]{iter: internal.TakeWhile(self.iter, predicate)} + return &streamImpl[T]{iter: ops.TakeWhile(self.iter, predicate)} } func (self *streamImpl[T]) SkipWhile(predicate func(T) bool) Stream[T] { - return &streamImpl[T]{iter: internal.SkipWhile(self.iter, predicate)} + return &streamImpl[T]{iter: ops.SkipWhile(self.iter, predicate)} } func (self *streamImpl[T]) ForEach(consumer func(T)) { - internal.ForEach(self.iter, consumer) + ops.ForEach(self.iter, consumer) } func (self *streamImpl[T]) StepBy(step uint) Stream[T] { - return &streamImpl[T]{iter: internal.StepBy(self.iter, step)} + return &streamImpl[T]{iter: ops.StepBy(self.iter, step)} +} + +func (self *streamImpl[T]) First() optional.Optional[T] { + return self.iter.Next() } func (self *streamImpl[T]) Last() optional.Optional[T] { - return internal.Last(self.iter) + return ops.Last(self.iter) } func (self *streamImpl[T]) Advancing(step uint) Stream[T] { - return &streamImpl[T]{iter: internal.Advancing(self.iter, step)} + return &streamImpl[T]{iter: ops.Advancing(self.iter, step)} } func (self *streamImpl[T]) IsSorted(ord cmp.OrdFunc[T]) bool { - return internal.IsSorted(self.iter, ord) + return ops.IsSorted(self.iter, ord) } diff --git a/iterator/stream/stream.go b/iterator/stream/stream.go index 9fb899b..0e5319e 100644 --- a/iterator/stream/stream.go +++ b/iterator/stream/stream.go @@ -6,30 +6,61 @@ import ( "github.com/go-board/std/optional" ) +// Stream is a lazy sequence of values of type T. +// It wraps an iterator.Iterator[T] and provides a lazy access to its elements. +// It also provides a way to chain operations on the stream. type Stream[T any] interface { iterator.Iterable[T] + // All returns true if all elements of the stream satisfy the predicate. All(predicate func(T) bool) bool + // Any returns true if any element of the stream satisfies the predicate. Any(predicate func(T) bool) bool + // Once returns true if the predicate is true for exactly one element of the stream satisfy the predicate. Once(predicate func(T) bool) bool + // None returns true if none of the elements of the stream satisfy the predicate. None(predicate func(T) bool) bool + // Chain returns a new stream that is the result of chaining the current stream with the given iterable. Chain(o iterator.Iterable[T]) Stream[T] + // ForEach calls the given function for each element of the stream. + ForEach(consumer func(T)) + // Map returns a new stream that is the result of applying the given function to each element of the stream. Map(transformer func(T) T) Stream[T] + // Filter returns a new stream that is the result of applying the given predicate to each element of the stream. Filter(predicate func(T) bool) Stream[T] + // Reduce returns an optional value of type T that is the result of applying the given function to each element of the stream. Reduce(reduce func(T, T) T) optional.Optional[T] + // Fold returns a value of type T that is the result of applying the given function to each element of the stream with the given initial value. + Fold(initial T, accumulator func(T, T) T) T + // Flatten returns a new stream that is the result of flattening each element in the current stream. Flatten(flatten func(T) iterator.Iterator[T]) Stream[T] + // Inspect does something with each element of the stream. Different from ForEach, this will return the stream itself. Inspect(inspect func(T)) Stream[T] + // MaxBy returns an optional value of type T that is the maximum element of the stream according to the given comparator. MaxBy(ord cmp.OrdFunc[T]) optional.Optional[T] + // MinBy returns an optional value of type T that is the minimum element of the stream according to the given comparator. MinBy(ord cmp.OrdFunc[T]) optional.Optional[T] - Equal(o iterator.Iterable[T], ord cmp.EqFunc[T]) bool + // EqualBy returns true if the two streams are equal according to the given comparator. + EqualBy(o iterator.Iterable[T], ord cmp.EqFunc[T]) bool + // Collect returns a slice of all the elements of the stream. Collect() []T + // Nth returns an optional value of type T that is the nth element of the stream. Nth(n uint) optional.Optional[T] + // Take returns a new stream that is the result of taking the given number of elements from the current stream. Take(n uint) Stream[T] + // Skip returns a new stream that is the result of skipping the given number of elements from the current stream. Skip(n uint) Stream[T] + // TakeWhile returns a new stream that is the result of taking elements from the current stream while the predicate is true. TakeWhile(predicate func(T) bool) Stream[T] + // SkipWhile returns a new stream that is the result of skipping elements from the current stream while the predicate is true. SkipWhile(predicate func(T) bool) Stream[T] - ForEach(consumer func(T)) + // StepBy returns a new stream that is the result of stepping by the given number of elements from the current stream. StepBy(step uint) Stream[T] + // First returns an optional value of type T that is the first element of the stream. + First() optional.Optional[T] + // Last returns an optional value of type T that is the last element of the stream. Last() optional.Optional[T] + // Advancing returns a new stream that is the result of advancing the current stream by the given number of elements. Advancing(step uint) Stream[T] + // IsSorted returns true if the stream is sorted according to the given comparator. IsSorted(ord cmp.OrdFunc[T]) bool }