Documentation
¶
Overview ¶
Package ez declares a Stream interface and implementations, allowing data stream operations to be applied in a functional style.
Example (Complex) ¶
Example_complex demonstrates complex stream transformations including filtering, mapping, and operations like shuffle, reverse, distinct, sortOrdered, and reduce using a sequence generated from the Fibonacci series.
rng := rand.New(rand.NewChaCha8([32]byte{}))
stream := ez.Convert(
ez.Pipe(fibonacci,
ez.Filter(func(i int) bool {
return i > 5
}),
ez.Map(func(i int) int {
return i / 2
}),
ez.Skip[int](10),
ez.Take[int](10),
ez.ShuffleWithRand[int](rng),
ez.Reverse[int],
), func(i int) float64 {
return math.Round(math.Sqrt(float64(i)) * math.Sin(float64(i)))
})
values := ez.Collect(stream)
fmt.Println("m:", values)
sorted := ez.Collect(ez.Pipe(ez.SliceStream(values), ez.Ordered[float64]))
fmt.Println("sorted:", sorted)
distinct := ez.Collect(ez.Pipe(ez.SliceStream(sorted), ez.Distinct[float64]))
fmt.Println("distinct:", distinct)
sum := ez.Reduce(stream, 0, func(a float64, b float64) float64 {
return a + b
})
fmt.Println("sum:", sum)
Output: m: [86 -34 -124 86 25 1 190 -26 5 58] sorted: [-124 -34 -26 1 5 25 58 86 86 190] distinct: [-124 -34 -26 1 5 25 58 86 190] sum: 267
Example (Stream) ¶
Example demonstrates the usage of various stream operations such as filtering, mapping, skipping, and taking elements from streams.
package main
import (
"fmt"
"github.com/justenwalker/ez"
"math"
)
// Example Streams
var (
fibonacci = ez.InfiniteStream(func(yield func(int) bool) {
a := 0
if !yield(a) {
return
}
b := 1
for yield(b) {
a, b = b, b+a
}
})
oneToTen = ez.FiniteStream(func(yield func(int) bool) {
for i := range 10 {
if !yield(i + 1) {
return
}
}
})
)
func main() {
// convert a slice to a stream
sliceStream := ez.SliceStream([]int{1, 2, 3, 4, 5, 6, 7})
// Pipe stream operations together with the `Pipe` function
intStream := ez.Pipe(fibonacci,
ez.Filter(func(i int) bool { return i > 5 }),
ez.Map(func(i int) int { return i / 2 }),
ez.Skip[int](10),
ez.Take[int](10),
ez.Reverse[int],
)
// Convert from a stream of one type to another
float64Stream := ez.Convert(intStream, func(i int) float64 {
return math.Round(math.Sqrt(float64(i)))
})
// Collect m into a slice from a Finite Stream.
values := ez.Collect(float64Stream)
fmt.Println("m:", values)
// Concatenate several streams together:
concat := ez.Concat(
oneToTen,
sliceStream,
ez.Pipe(fibonacci, ez.Take[int](10)),
)
// Reduce a stream to a single value
sum := ez.Reduce(concat, 0, func(acc int, v int) int { return acc + v })
fmt.Println("sum:", sum)
}
Output: m: [194 152 120 94 74 58 46 36 28 22] sum: 171
Example (Stream2) ¶
Example demonstrates the usage of various stream operations such as filtering, mapping, skipping, and taking elements from streams.
package main
import (
"fmt"
"github.com/justenwalker/ez"
"math"
)
// Example Streams
var fibonacci = ez.InfiniteStream(func(yield func(int) bool) {
a := 0
if !yield(a) {
return
}
b := 1
for yield(b) {
a, b = b, b+a
}
})
func main() {
zipStream2 := ez.Zip(
ez.InfiniteStream(func(yield func(int) bool) {
i := 0
for {
if !yield(i) {
return
}
i++
}
}),
fibonacci,
)
// Pipe stream operations together with the `Pipe` function
intStream := ez.Pipe2(zipStream2,
ez.Filter2(func(l, r int) bool { return r > 5 }),
ez.Map2(func(l, r int) (int, int) { return l, r * 2 }),
ez.Skip2[int, int](10),
ez.Take2[int, int](10),
ez.Reverse2[int, int],
)
// Convert from a stream of one type to another
float64Stream := ez.Convert2(intStream, func(l, r int) (int, float64) {
return l, math.Round(math.Sqrt(float64(r)))
})
// Collect m into a slice from a Finite Stream.
leftValues, rightValues := ez.Collect2(float64Stream)
fmt.Println("left:", leftValues)
fmt.Println("right:", rightValues)
// Concatenate several streams together:
concat := ez.Concat2(
ez.Pipe2(zipStream2, ez.Take2[int, int](3)),
ez.Pipe2(zipStream2, ez.Skip2[int, int](3), ez.Take2[int, int](3)),
ez.Pipe2(zipStream2, ez.Skip2[int, int](6), ez.Take2[int, int](3)),
)
// Reduce a stream to a single value
leftSum := ez.Reduce(ez.Left(concat), 0, func(acc int, v int) int { return acc + v })
fmt.Println("leftSum:", leftSum)
rightSum := ez.Reduce(ez.Right(concat), 0, func(acc int, v int) int { return acc + v })
fmt.Println("rightSum:", rightSum)
}
Output: left: [25 24 23 22 21 20 19 18 17 16] right: [387 305 239 188 148 116 91 72 57 44] leftSum: 36 rightSum: 54
Index ¶
- Variables
- func AssertFinite(stream any)
- func Collect[D any](stream Stream[D]) []D
- func Collect2[L any, R any](stream2 Stream2[L, R]) (left []L, right []R)
- func ConvertToMap[K comparable, V any](stream2 Stream2[K, V]) map[K]V
- func Filter[D any](predicate func(v D) bool) func(stream Stream[D]) Stream[D]
- func Filter2[L, R any](predicate func(l L, r R) bool) func(stream Stream2[L, R]) Stream2[L, R]
- func IsFinite(stream any) bool
- func Map[D any](mapFn func(v D) D) func(stream Stream[D]) Stream[D]
- func Map2[L, R any](mapFn func(l L, r R) (L, R)) func(stream2 Stream2[L, R]) Stream2[L, R]
- func Reduce[D any](stream Stream[D], initial D, accumFunc func(acc D, d D) D) D
- func ShuffleWithRand[D any](rng *rand.Rand) func(stream Stream[D]) Stream[D]
- func Size(stream any) int
- func Skip[D any](n int) func(stream Stream[D]) Stream[D]
- func Skip2[L any, R any](n int) func(stream2 Stream2[L, R]) Stream2[L, R]
- func Sort[D any](cmp func(a, b D) int) func(stream Stream[D]) Stream[D]
- func Take[D any](n int) func(stream Stream[D]) Stream[D]
- func Take2[L, R any](n int) func(stream2 Stream2[L, R]) Stream2[L, R]
- type Finite
- type Stream
- func AssumeFinite[D any](stream Stream[D]) Stream[D]
- func Concat[D any](streams ...Stream[D]) Stream[D]
- func Convert[D, R any](stream Stream[D], convertFunc func(v D) R) Stream[R]
- func Distinct[D comparable](stream Stream[D]) Stream[D]
- func FiniteStream[D any](seq iter.Seq[D]) Stream[D]
- func FiniteStreamWithSize[D any](seq iter.Seq[D], size int) Stream[D]
- func InfiniteStream[D any](seq iter.Seq[D]) Stream[D]
- func Left[L any, R any](stream2 Stream2[L, R]) Stream[L]
- func Ordered[D cmp.Ordered](stream Stream[D]) Stream[D]
- func Pipe[D any](stream Stream[D], pipeFunc ...func(iter Stream[D]) Stream[D]) Stream[D]
- func Reverse[D any](stream Stream[D]) Stream[D]
- func Right[L any, R any](stream2 Stream2[L, R]) Stream[R]
- func Shuffle[D any](stream Stream[D]) Stream[D]
- func SliceStream[D any](values []D) Stream[D]
- type Stream2
- func AssumeFinite2[L, R any](stream Stream2[L, R]) Stream2[L, R]
- func Concat2[L, R any](streams ...Stream2[L, R]) Stream2[L, R]
- func Convert2[L1 any, R1 any, L2 any, R2 any](stream2 Stream2[L1, R1], convertFunc func(v1 L1, v2 R1) (L2, R2)) Stream2[L2, R2]
- func FiniteStream2[L any, R any](seq2 iter.Seq2[L, R]) Stream2[L, R]
- func FiniteStream2WithSize[L any, R any](seq2 iter.Seq2[L, R], size int) Stream2[L, R]
- func InfiniteStream2[L any, R any](seq2 iter.Seq2[L, R]) Stream2[L, R]
- func MapKVStream[K comparable, V any](m map[K]V) Stream2[K, V]
- func MapKVStreamOrdered[K cmp.Ordered, V any](m map[K]V) Stream2[K, V]
- func MapKVStreamSorted[K comparable, V any](m map[K]V, cmp func(a, b K) int) Stream2[K, V]
- func Pipe2[K any, V any](stream Stream2[K, V], pipeFunc ...func(iter Stream2[K, V]) Stream2[K, V]) Stream2[K, V]
- func Reverse2[L, R any](stream Stream2[L, R]) Stream2[L, R]
- func Shuffle2[L, R any](stream2 Stream2[L, R]) Stream2[L, R]
- func Shuffle2WithRand[L, R any](rng *rand.Rand, stream2 Stream2[L, R]) Stream2[L, R]
- func Swap2[L, R any](stream2 Stream2[L, R]) Stream2[R, L]
- func Zip[L any, R any](left Stream[L], right Stream[R]) Stream2[L, R]
- func ZipSliceStream2[L any, R any](left []L, right []R) Stream2[L, R]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInfiniteSequence = errors.New("infinite sequence")
ErrInfiniteSequence indicates that an operation requiring a finite Stream has been given an InfiniteStream. Certain operations like Collect and Reverse only work on Finite streams.
Functions ¶
func AssertFinite ¶
func AssertFinite(stream any)
AssertFinite asserts that the given stream is finite. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Collect ¶
Collect returns a slice of all the elements collected from the stream. If the Stream implements `Collect() []D`, that implementation is used. Otherwise, this function collects all elements of the Stream's sequence. If the Stream implements `Size() int`, it can be used to reduce allocations, since the slice can be pre-allocated. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func ConvertToMap ¶
func ConvertToMap[K comparable, V any](stream2 Stream2[K, V]) map[K]V
ConvertToMap converts the Stream2 to a Map of L to R values.
func IsFinite ¶
IsFinite checks whether a given Stream is finite by asserting if it implements the Finite interface.
func Reduce ¶
Reduce processes elements of a stream sequentially and applies an accumulator function to reduce them to a single value.
func ShuffleWithRand ¶
ShuffleWithRand returns a new Stream with data in a randomized order determined by the given random number generator. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Size ¶
Size returns the maximum number of elements in the stream, if the stream has a Size method. It returns -1 if the Stream size is unknown; for instance: an InfiniteStream, or FiniteStream with no size.
func Sort ¶
Sort returns a new stream with the data elements in sorted order. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
Types ¶
type Finite ¶
type Finite interface {
Finite() bool
}
Finite is a marker interface to detect if a Stream is finite. A Stream must be finite in order for certain operations to be performed such as Collect, or Sort, or Shuffle.
type Stream ¶
Stream represents a generic interface for a stream of values.
func AssumeFinite ¶
AssumeFinite converts a given Stream into a Finite Stream. The caller guarantees that the stream given is finite. If the stream given is not finite, the behavior is undefined, but likely will result in a program hang/crash. If the given stream is already finite, ie: IsFinite(stream) == true, then this function returns its input unchanged.
func Concat ¶
Concat concatenates one or more streams together. If all the Streams given are Finite, the resulting concatenation is also Finite. If all the streams given have Size, then the resulting Stream is Finite, and also has a Size.
func Convert ¶
Convert converts a stream of type D to a stream of type R using the provided conversion function.
func Distinct ¶
func Distinct[D comparable](stream Stream[D]) Stream[D]
Distinct returns a new stream containing only the distinct elements of the original stream by filtering out duplicates. NOTE: the memory consumed by this stream is unbounded if the Stream is not Finite.
func FiniteStream ¶
FiniteStream returns a Finite Stream backed by the given sequence. The sequence provided is assumed to be finite. If the sequence given is not finite, the behavior is undefined, but likely will result in a program hang/crash.
func FiniteStreamWithSize ¶
FiniteStreamWithSize returns a Finite Stream backed by the given sequence for which the size is known. The sequence provided is assumed to be finite and have a most number of data elements given. If the sequence given is not finite, the behavior is undefined.
func InfiniteStream ¶
InfiniteStream returns a new Stream containing an infinite data sequence. This function is used when the underlying sequence does not have a predefined end.
func Pipe ¶
Pipe returns a stream after the provided operations have been applied to it in sequence.
func Reverse ¶
Reverse returns a new stream with the data elements in reverse order. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Shuffle ¶
Shuffle returns a new Stream with data in a randomized order. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func SliceStream ¶
SliceStream returns a Finite Stream backed by the given slice of data elements. Since slices are finite, the stream returned by this function is Finite. Since slices have a known size, the stream returned by this function has Size.
type Stream2 ¶
Stream2 represents a generic interface for a stream of tuples.
func AssumeFinite2 ¶
AssumeFinite2 converts a given Stream2 into a Finite Stream2. The caller guarantees that the stream given is finite. If the stream given is not finite, the behavior is undefined, but likely will result in a program hang/crash. If the given stream is already finite, ie: IsFinite(stream) == true, then this function returns its input unchanged.
func Concat2 ¶
Concat2 concatenates one or more streams together. If all the Streams given are Finite, the resulting concatenation is also Finite. If all the streams given have Size, then the resulting Stream is Finite, and also has a Size.
func Convert2 ¶
func Convert2[L1 any, R1 any, L2 any, R2 any](stream2 Stream2[L1, R1], convertFunc func(v1 L1, v2 R1) (L2, R2)) Stream2[L2, R2]
Convert2 converts a Stream2 of one type to a Stream2 of another type using convertFunc.
func FiniteStream2 ¶
FiniteStream2 returns a Finite Stream2 backed by the given sequence. The sequence provided is assumed to be finite. If the sequence given is not finite, the behavior is undefined, but likely will result in a program hang/crash.
func FiniteStream2WithSize ¶
FiniteStream2WithSize returns a Finite Stream2 backed by the given sequence for which the size is known. The sequence provided is assumed to be finite and have a most number of data elements given. If the sequence given is not finite, the behavior is undefined.
func InfiniteStream2 ¶
InfiniteStream2 returns a new Stream2 containing an infinite data sequence.
func MapKVStream ¶
func MapKVStream[K comparable, V any](m map[K]V) Stream2[K, V]
MapKVStream converts the given map into a Stream2. NOTE: the stream will produce items in an indeterminate order. For a well-defined ordering, use MapKVStreamOrdered or MapKVStreamSorted.
func MapKVStreamOrdered ¶
MapKVStreamOrdered converts the given map into a Stream2 using the natural order of the keys.
func MapKVStreamSorted ¶
func MapKVStreamSorted[K comparable, V any](m map[K]V, cmp func(a, b K) int) Stream2[K, V]
MapKVStreamSorted converts the given map into a Stream2 using the provided key ordering.
func Pipe2 ¶
func Pipe2[K any, V any](stream Stream2[K, V], pipeFunc ...func(iter Stream2[K, V]) Stream2[K, V]) Stream2[K, V]
Pipe2 returns a Stream2 after the provided operations have been applied to it in sequence.
func Reverse2 ¶
Reverse2 returns a new stream with the data elements in reverse order. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Shuffle2 ¶
Shuffle2 returns a new Stream2 with data in a randomized order. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Shuffle2WithRand ¶
Shuffle2WithRand returns a new Stream2 with data in a randomized order determined by the given random number generator. NOTE: If stream is not finite, this function will panic with ErrInfiniteSequence.
func Swap2 ¶
Swap2 takes a Stream2 with left and right elements, and returns a new Stream2 with the elements swapped.
func Zip ¶
Zip returns a Stream2 produced by zipping a key and value stream together. If the both streams are infinite, the returns Stream2 is also infinite. If any of the given streams is finite, then a finite Stream2 will be returned having a length of the smallest size between the two streams.
func ZipSliceStream2 ¶
ZipSliceStream2 converts the given pair of slices into a Stream2 by zipping them together. If the slices provided are not the same length, the stream returned will have the length of the smallest slice provided.