Skip to content

Commit

Permalink
Add Limit(n) to the Seq interface
Browse files Browse the repository at this point in the history
  • Loading branch information
kamstrup committed Feb 17, 2023
1 parent 38f0414 commit 11f80f3
Show file tree
Hide file tree
Showing 22 changed files with 118 additions and 6 deletions.
1 change: 0 additions & 1 deletion README.md
Expand Up @@ -420,7 +420,6 @@ TODO
```
API CHANGES:
* Do we need to change seq.Go() to enable better error handling?
* Add Seq.Limit(n) method on Seq interface?
POTENTIAL FUTURE FEATURES (unordered)
* Something for context.Context? Support cancel() cb and Done() chans? fncontext package...
Expand Down
4 changes: 4 additions & 0 deletions io/reader.go
Expand Up @@ -108,6 +108,10 @@ func (r Reader) ToSlice() BufferSlice {
return seq.Reduce(seq.Append[[]byte], nil, r.seq()).Or(nil) // careful: errors silently dropped
}

func (r Reader) Limit(n int) BufferSeq {
return seq.LimitOf[[]byte](r, n)
}

func (r Reader) Take(n int) (BufferSlice, BufferSeq) {
var (
res [][]byte
Expand Down
4 changes: 4 additions & 0 deletions io/scanner.go
Expand Up @@ -58,6 +58,10 @@ func (s scannerSeq) ToSlice() BufferSlice {
return tokens
}

func (s scannerSeq) Limit(n int) BufferSeq {
return seq.LimitOf[[]byte](s, n)
}

func (s scannerSeq) Take(n int) (BufferSlice, BufferSeq) {
var tokens [][]byte
for i := 0; i < n && s.scanner.Scan(); i++ {
Expand Down
4 changes: 4 additions & 0 deletions json/decoder.go
Expand Up @@ -53,6 +53,10 @@ func (d decoderSeq[T]) ToSlice() seq.Slice[T] {
return arr
}

func (d decoderSeq[T]) Limit(n int) seq.Seq[T] {
return seq.LimitOf[T](d, n)
}

func (d decoderSeq[T]) Take(n int) (seq.Slice[T], seq.Seq[T]) {
var (
arr = make([]T, 0, n)
Expand Down
4 changes: 4 additions & 0 deletions seq/chan.go
Expand Up @@ -35,6 +35,10 @@ func (c Chan[T]) ToSlice() Slice[T] {
return Reduce(Append[T], nil, c.Seq()).Or(nil) // careful: errors silently dropped
}

func (c Chan[T]) Limit(n int) Seq[T] {
return LimitOf[T](c, n)
}

func (c Chan[T]) Take(n int) (Slice[T], Seq[T]) {
if n == 0 {
return []T{}, c
Expand Down
4 changes: 4 additions & 0 deletions seq/concat.go
Expand Up @@ -85,6 +85,10 @@ func (c concatSeq[T]) ToSlice() Slice[T] {
return buf
}

func (c concatSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](c, n)
}

func (c concatSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n <= 0 {
return []T{}, c
Expand Down
9 changes: 5 additions & 4 deletions seq/error.go
Expand Up @@ -52,6 +52,10 @@ func (e errorSeq[T]) ToSlice() Slice[T] {
return nil
}

func (e errorSeq[T]) Limit(n int) Seq[T] {
return e
}

func (e errorSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n < 0 {
panic("must take >= 0 elements")
Expand Down Expand Up @@ -83,8 +87,5 @@ func (e errorSeq[T]) First() (opt.Opt[T], Seq[T]) {
}

func (e errorSeq[T]) Map(shaper FuncMap[T, T]) Seq[T] {
return mappedSeq[T, T]{
f: shaper,
seq: e,
}
return e
}
7 changes: 7 additions & 0 deletions seq/limit.go
Expand Up @@ -75,6 +75,13 @@ func (l limitSeq[T]) ToSlice() Slice[T] {
return arr
}

func (l limitSeq[T]) Limit(n int) Seq[T] {
if n < l.limit {
return LimitOf[T](l, n)
}
return l
}

func (l limitSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n > l.limit {
n = l.limit
Expand Down
4 changes: 4 additions & 0 deletions seq/map.go
Expand Up @@ -83,6 +83,10 @@ func (a Map[K, V]) ToSlice() Slice[Tuple[K, V]] {
return arr
}

func (a Map[K, V]) Limit(n int) Seq[Tuple[K, V]] {
return LimitOf[Tuple[K, V]](a, n)
}

func (a Map[K, V]) Take(n int) (Slice[Tuple[K, V]], Seq[Tuple[K, V]]) {
// Taking the "first n elements" from a map[K]V does *almost* never make sense,
// since maps in Go a deliberately not ordered consistently.
Expand Down
4 changes: 4 additions & 0 deletions seq/mapping.go
Expand Up @@ -73,6 +73,10 @@ func (m mappedSeq[S, T]) ToSlice() Slice[T] {
}
}

func (m mappedSeq[S, T]) Limit(n int) Seq[T] {
return LimitOf[T](m, n)
}

func (m mappedSeq[S, T]) Take(n int) (Slice[T], Seq[T]) {
var (
head Slice[S]
Expand Down
4 changes: 4 additions & 0 deletions seq/prepend.go
Expand Up @@ -58,6 +58,10 @@ func (p prepSeq[T]) ToSlice() Slice[T] {
return arr
}

func (p prepSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](p, n)
}

func (p prepSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n == 0 {
return Slice[T]{}, p
Expand Down
26 changes: 26 additions & 0 deletions seq/range.go
Expand Up @@ -119,6 +119,32 @@ func (r rangeSeq[N]) ToSlice() Slice[N] {
return arr
}

func (r rangeSeq[N]) Limit(n int) Seq[N] {
end := int(r.from) + int(r.step)*n

// are we ascending?
if r.to > r.from {
if end < int(r.to) {
return rangeSeq[N]{
from: r.from,
to: N(end),
step: r.step,
}
}
return r
}

// we are descending
if end > int(r.to) {
return rangeSeq[N]{
from: r.from,
to: N(end),
step: r.step,
}
}
return r
}

func (r rangeSeq[N]) Take(n int) (Slice[N], Seq[N]) {
sz, _ := r.Len()
if n >= sz {
Expand Down
7 changes: 6 additions & 1 deletion seq/seq.go
Expand Up @@ -44,7 +44,12 @@ type Seq[T any] interface {
// ToSlice executes the Seq and stores all elements in memory as a Slice.
// Recall that all functions and operations that works on a normal slice []T, also work directly on a Slice[T].
ToSlice() Slice[T]
// Take executes up to the first N elements of the Seq and returns the rest in a tail Seq
// Limit returns a lazy Seq with maximally n elements.
// The Take method is related, but Take is different in that it executes the first n elements and returns the tail.
// Limit is lazy, and can as such not return a tail.
Limit(n int) Seq[T]
// Take executes up to the first N elements of the Seq and returns the rest in a tail Seq.
// The Limit method is related, but different because Limit is lazy and does not return a tail.
Take(int) (Slice[T], Seq[T])
// TakeWhile executes the Seq while Predicate returns true,
// then returns those elements in a Slice and the rest in a tail Seq.
Expand Down
4 changes: 4 additions & 0 deletions seq/set.go
Expand Up @@ -75,6 +75,10 @@ func (s Set[K]) ToSlice() Slice[K] {
return arr
}

func (s Set[T]) Limit(n int) Seq[T] {
return LimitOf[T](s, n)
}

func (s Set[K]) Take(n int) (Slice[K], Seq[K]) {
// Taking the "first n elements" from a map[K]V does *almost* never make sense,
// since maps in Go a deliberately not ordered consistently.
Expand Down
4 changes: 4 additions & 0 deletions seq/singlet.go
Expand Up @@ -44,6 +44,10 @@ func (s singletSeq[T]) ToSlice() Slice[T] {
return Slice[T]{s.val}
}

func (s singletSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](s, n)
}

func (s singletSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n == 0 {
return Slice[T]{}, s
Expand Down
7 changes: 7 additions & 0 deletions seq/slice.go
Expand Up @@ -84,6 +84,13 @@ func (a Slice[T]) ToSlice() Slice[T] {
return a
}

func (a Slice[T]) Limit(n int) Seq[T] {
if len(a) <= n {
return a
}
return a[:n]
}

func (a Slice[T]) Take(n int) (Slice[T], Seq[T]) {
if len(a) <= n {
return a, Empty[T]()
Expand Down
4 changes: 4 additions & 0 deletions seq/source.go
Expand Up @@ -54,6 +54,10 @@ func (s sourceSeq[T]) ToSlice() Slice[T] {
panic("cannot create Slice of infinite source")
}

func (s sourceSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](s, n)
}

func (s sourceSeq[T]) Take(n int) (Slice[T], Seq[T]) {
arr := make([]T, n)
for i := 0; i < n; i++ {
Expand Down
4 changes: 4 additions & 0 deletions seq/split.go
Expand Up @@ -79,6 +79,10 @@ func (s splitSeq[T]) ToSlice() Slice[Seq[T]] {
return arr
}

func (s splitSeq[T]) Limit(n int) Seq[Seq[T]] {
return LimitOf[Seq[T]](s, n)
}

func (s splitSeq[T]) Take(n int) (Slice[Seq[T]], Seq[Seq[T]]) {
if n == 0 {
return []Seq[T]{}, s
Expand Down
7 changes: 7 additions & 0 deletions seq/string.go
Expand Up @@ -40,6 +40,13 @@ func (s String) ToSlice() Slice[byte] {
return []byte(s)
}

func (s String) Limit(n int) Seq[byte] {
if len(s) <= n {
return s
}
return s[:n]
}

func (s String) Take(n int) (Slice[byte], Seq[byte]) {
if len(s) <= n {
return []byte(s), Empty[byte]()
Expand Down
4 changes: 4 additions & 0 deletions seq/where.go
Expand Up @@ -54,6 +54,10 @@ func (ws whereSeq[T]) ToSlice() Slice[T] {
return arr
}

func (ws whereSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](ws, n)
}

func (ws whereSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if l, _ := ws.Len(); l == 0 || n == 0 {
return Slice[T](nil), Empty[T]()
Expand Down
4 changes: 4 additions & 0 deletions seq/while.go
Expand Up @@ -51,6 +51,10 @@ func (w whileSeq[T]) ToSlice() Slice[T] {
return head
}

func (w whileSeq[T]) Limit(n int) Seq[T] {
return LimitOf[T](w, n)
}

func (w whileSeq[T]) Take(n int) (Slice[T], Seq[T]) {
if n == 0 {
return []T{}, w
Expand Down
4 changes: 4 additions & 0 deletions seq/zip.go
Expand Up @@ -97,6 +97,10 @@ func (z zipSeq[X, Y]) ToSlice() Slice[Tuple[X, Y]] {
return arr
}

func (z zipSeq[X, Y]) Limit(n int) Seq[Tuple[X, Y]] {
return LimitOf[Tuple[X, Y]](z, n)
}

func (z zipSeq[X, Y]) Take(n int) (Slice[Tuple[X, Y]], Seq[Tuple[X, Y]]) {
var (
arr []Tuple[X, Y]
Expand Down

0 comments on commit 11f80f3

Please sign in to comment.