chains

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 1, 2024 License: BSD-3-Clause Imports: 1 Imported by: 0

README

Chained Iterators in Go

I haven't done much in Go lately, and I definitely haven't played with generics or iterators yet. Why not do both?

So now you can do this:

myArray := []int{1, 2, 3}

returnArray := ChainFromSlice(
    []int{8, 10, 145, 3},
).Map(
    func(i int) int {
        return i * 3
    },
).Filter(
    func(i int) bool {
        return i%2 == 0
    },
).Slice()
// returnArray == []int{24, 30}

This library is ment to fill a void in some of the niceness I get in Python and Ruby -- you'll note there is a whole subset of Python's itertoools library here.

Examples

Interesting examples live in cookbook_test.

Warts

The Go templating system is a little limited, so you can't do something like this:

arrayOfStrings := ChainFromSlice(
    []int{8, 10, 145, 3},
).Map(
    // Compiler can't infer you're going from Chain[int] to Chain[string]
    func(i int) string {
        return fmt.Sprintf("%v", i)
    },
)

The generic system does not allow for templated methods, so chaining methods and expecting to go from Chain[T] to Chain[V] isn't possible.

You need to give the templating system a hint with a junction, telling it there's 2 types involved:

mapFunc := func(i int) string { return fmt.Sprintf("%v", i) }
array := []int{1, 2, 3, 4}
// Converting type in .Map(), so the generic has to be aware of both types
returnArray := ChainJunction[int, string](ChainFromSlice(
    array,
).Filter(
    func(i int) bool {
        return i%2 == 0
    },
)).Map(
    mapFunc,
).Slice()
// secondreturnArrayArray == []string{"2", "4"}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Accumulate added in v0.0.7

func Accumulate[T, V any](input iter.Seq[T], collectFunc func(V, T) V, zeroValue V) iter.Seq[V]

Accumulate takes an initial value, a reduce function, and an iterable and returns each result of applying the function iteratively.

func All

func All[T any](input iter.Seq[T], predicateFunc func(T) bool) bool

All takes an iterator and returns true if the sequence is empty or all items match the predicate

func All2

func All2[T, V any](input iter.Seq2[T, V], predicateFunc func(T, V) bool) bool

All2 takes an iterator and returns true if the sequence is empty or all items match the predicate

func AllPermutations added in v0.0.5

func AllPermutations[T any](vals []T) iter.Seq[[]T]

AllPermutations will yield all permutations without replacement of every subset of items in the sequence of all length

func Any

func Any[T any](input iter.Seq[T], predicateFunc func(T) bool) bool

Any takes an iterator and returns true if the sequence is empty or any item matches the predicate

func Any2

func Any2[T, V any](input iter.Seq2[T, V], predicateFunc func(T, V) bool) bool

Any2 takes an iterator and returns true if the sequence is empty or any item matches the predicate

func Combinations added in v0.0.5

func Combinations[T any](vals []T) iter.Seq[[]T]

Combinations will yield all combinations without replacement of the entire slice

func CombinationsOfLength added in v0.0.5

func CombinationsOfLength[T any](vals []T, length int) iter.Seq[[]T]

CombinationsOfLength will yield all combinations without replacement of a specified length

func Compact added in v0.0.7

func Compact[T comparable](input iter.Seq[T]) iter.Seq[T]

Compact yields anything that is not the zero value.

func Count

func Count[T any](input iter.Seq[T]) int

Count returns the length of the exhusted iterator.

func Cycle

func Cycle[T any](input iter.Seq[T]) iter.Seq[T]

Cycle yields every item in the sequence indefinitely, starting from the beginning once exhausted. Imagine Repeat, but infinity times.

func DropUntil

func DropUntil[T any](filterFunc func(T) bool, input iter.Seq[T]) iter.Seq[T]

DropUntil does not start producing values until the filterFunc returns true the first time

func Each

func Each[T any](in []T) iter.Seq[T]

Each wraps a slice as an iterable. Only iteresting when applying higher-level functions like Map or Filter.

func Filter

func Filter[T any](input iter.Seq[T], predicateFunc func(T) bool) iter.Seq[T]

Filter takes an iterator and only yields the items that pass the filter function check.

func Filter2

func Filter2[T, V any](input iter.Seq2[T, V], predicateFunc func(T, V) bool) iter.Seq2[T, V]

Filter2 takes an iterator and only yields the items that pass the filter function check.

func First added in v0.0.7

func First[T any](input iter.Seq[T]) T

First returns the first value found

func FirstAndRest

func FirstAndRest[T any](input iter.Seq[T]) (T, iter.Seq[T])

FirstAndRest returns CAR/CDR, the first item from the iterable followed by an iterable for the rest of it.

func Flatten

func Flatten[T any](sequences iter.Seq[iter.Seq[T]]) iter.Seq[T]

Flatten takes any number of iterables and combines them into one

func Flatten2

func Flatten2[T, V any](sequences iter.Seq[iter.Seq2[T, V]]) iter.Seq2[T, V]

Flatten takes any number of iterables and combines them into one

func FlattenArgs

func FlattenArgs[T any](sequences ...iter.Seq[T]) iter.Seq[T]

FlattenArgs takes any number of iterable args and combines them into one

func FlattenArgs2

func FlattenArgs2[T, V any](sequences ...iter.Seq2[T, V]) iter.Seq2[T, V]

FlattenArgs takes any number of iterable args and combines them into one

func GroupBy

func GroupBy[T any, K comparable](keyFunc func(T) K, input iter.Seq[T]) func(func(K, iter.Seq[T]) bool)

GroupBy returns an iterator of iterators, with each first-level iteration yielding a key and an iterator of values that map to that key value in sequence. Like Uniq, if the same key appears disjointedly it will show up multiple times in iteration.

func Last added in v0.0.7

func Last[T any](input iter.Seq[T]) T

First returns the first value found

func Lengthen

func Lengthen[T any](input iter.Seq[T], repeats int) iter.Seq[T]

Lengthen will yield every element of the provided sequence up to repeats times; 3 x {1 2 3} -> { 1 1 1 2 2 2 3 3 3 }

func Map

func Map[T, V any](input iter.Seq[T], mapFunc func(T) V) iter.Seq[V]

Map takes an iterator and applies a function to each element.

func Map2

func Map2[T, V, K any](input iter.Seq2[T, V], mapFunc func(T, V) K) iter.Seq[K]

Map2 takes an iterator and applies a function to each element.

func Pairwise added in v0.0.7

func Pairwise[T, V any](s1 iter.Seq[T], s2 iter.Seq[V]) iter.Seq2[T, V]

Pairwise will yield all possible combinations of the two iterators

func Partition added in v0.0.7

func Partition[T any](in iter.Seq[T], predicateFunction func(T) bool) (iter.Seq[T], iter.Seq[T])

Partition splits one iterator into two based on the predicate function

func PastOffset

func PastOffset[T any](offset int, input iter.Seq[T]) iter.Seq[T]

PastOffset starts iterating at the zero-based index

func Permutations

func Permutations[T any](vals []T) iter.Seq[[]T]

Permutations will yield all possible orderings of the slice

func PermutationsOfLength

func PermutationsOfLength[T any](vals []T, length int) iter.Seq[[]T]

PermutationsOfLength will yield all combinations without replacement of a specified length

func PermutationsOfLengthWithReplacement

func PermutationsOfLengthWithReplacement[T any](vals []T, length int) iter.Seq[[]T]

PermutationsOfLengthWithReplacement will yield all combinations without replacement of a specified length

func PermutationsWithReplacement

func PermutationsWithReplacement[T any](vals []T) iter.Seq[[]T]

PermutationsWithReplacement will yield all possible orderings of the slice

func Reduce

func Reduce[T any](input iter.Seq[T], collectFunc func(T, T) T) T

Reduce takes a reduce function, and an iterable and returns the final result of applying the function iteratively.

func ReduceWithZero

func ReduceWithZero[T, V any](input iter.Seq[T], collectFunc func(V, T) V, zeroValue V) V

ReduceWithZero takes an initial value, a reduce function, and an iterable and returns the final result of applying the function iteratively.

func Repeat

func Repeat[T any](input iter.Seq[T], repeats int) iter.Seq[T]

Repeat will yield every element of the provided sequence up to repeats times; 3 x {1 2 3} -> { 1 2 3 1 2 3 1 2 3}

func Rotate

func Rotate[T any](repeats int, input iter.Seq[T]) iter.Seq[T]

Rotate will yield every element of the provided sequence, rotating the first element to the end; { 1 2 3 4 5 } -> { 2 3 4 5 1 }

func TakeWhile

func TakeWhile[T any](filterFunc func(T) bool, input iter.Seq[T]) iter.Seq[T]

TakeWhile stops iterating once the filterFunc returns false

func Tap

func Tap[T any](input iter.Seq[T], visitor func(T)) iter.Seq[T]

Tap visits each item with the visitor function but passes each item along.

func Tap2

func Tap2[T, V any](input iter.Seq2[T, V], visitor func(T, V)) iter.Seq2[T, V]

Tap2 visits each item with the visitor function but passes each item along.

func Tee

func Tee[T any](in iter.Seq[T]) (iter.Seq[T], iter.Seq[T])

Tee splits one iterator into two

func ToSlice added in v0.0.7

func ToSlice[T any](input iter.Seq[T]) []T

ToSlice makes a slice

func Uniq

func Uniq[T comparable](offset int, input iter.Seq[T]) iter.Seq[T]

Uniq returns the first value in a sequence, omitting duplicates. If a duplicate shows up further in the sequence, it will show up again. For example, {1 1 2 2 3 3 4} will yield {1 2 3 4} but {1 1 2 2 1 1 4} will yield {1 2 1 4}

func UntilOffset

func UntilOffset[T any](offset int, input iter.Seq[T]) iter.Seq[T]

UntilOffset stops iterating at the zero-based index

func Zip

func Zip[T, V any](input1 iter.Seq[T], input2 iter.Seq[V]) iter.Seq2[T, V]

Zip takes two sequences and combines them into one (up to length of shortest)

func ZipLongest

func ZipLongest[T, V any](input1 iter.Seq[T], input2 iter.Seq[V], fillerOne T, fillerTwo V) iter.Seq2[T, V]

ZipLongest takes two sequences and combines them into one (up to length of longest) via zipfunc, using fillerOne/fillerTwo as defaults if one is exhausted

Types

type IterableSequence

type IterableSequence[T any] struct {
	// contains filtered or unexported fields
}

IterableSequence is an opaque wrapper on an iterator to allow for chained methods.

func ChainFromIterator

func ChainFromIterator[T any](inFunc func(func(T) bool)) *IterableSequence[T]

Chain creates an chainable IterableSequence from an existing iterator.

func ChainFromSlice

func ChainFromSlice[T any](in []T) *IterableSequence[T]

ChainFromSlice creates an chainable IterableSequence from a slice.

func (*IterableSequence[T]) All

func (iter *IterableSequence[T]) All(predicateFunc func(T) bool) bool

func (*IterableSequence[T]) Any

func (iter *IterableSequence[T]) Any(predicateFunc func(T) bool) bool

func (*IterableSequence[T]) Count

func (iter *IterableSequence[T]) Count() int

func (*IterableSequence[T]) Each

func (iter *IterableSequence[T]) Each() func(func(T) bool)

Each is the final point to get an iterator out of an IterableSequence. After chaining your various .Map(...).Filter(..)... do a `range .Each()` to iterate over it in your code.

func (*IterableSequence[T]) Filter

func (iter *IterableSequence[T]) Filter(filterFunc func(T) bool) *IterableSequence[T]

func (*IterableSequence[T]) Map

func (iter *IterableSequence[T]) Map(mapFunc func(T) T) *IterableSequence[T]

Map is the classic function map -- takes a function, applies it to each item in the iterator, and yields that result

func (*IterableSequence[T]) Partition added in v0.0.7

func (iter *IterableSequence[T]) Partition(predicateFunc func(T) bool) (*IterableSequence[T], *IterableSequence[T])

func (*IterableSequence[T]) Reduce

func (iter *IterableSequence[T]) Reduce(reduceFunc func(T, T) T) T

Reduce is the classic function reduce -- takes a function, applies it to each item in the iterator along with its prior value, and yields that result

func (*IterableSequence[T]) ReduceWithZero

func (iter *IterableSequence[T]) ReduceWithZero(reduceFunc func(T, T) T, zeroValue T) T

func (*IterableSequence[T]) Slice

func (iter *IterableSequence[T]) Slice() []T

func (*IterableSequence[T]) Tap

func (iter *IterableSequence[T]) Tap(visitor func(T)) *IterableSequence[T]

Tap is a borrowed Rubyism -- it takes each item and passes it along, but feeds it to a function to visit first. Useful for calling methods, sanitizing fields, etc.

func (*IterableSequence[T]) Zip

func (iter *IterableSequence[T]) Zip(i *IterableSequence[T]) *IterableSequence2[T, T]

func (*IterableSequence[T]) ZipLongest

func (iter *IterableSequence[T]) ZipLongest(zeroValue T, i *IterableSequence[T]) *IterableSequence2[T, T]

type IterableSequence2

type IterableSequence2[T, V any] struct {
	// contains filtered or unexported fields
}

IterableSequence2 is an opaque wrapper on a two-item iterator to allow for chained methods.

func Chain2FromIterator

func Chain2FromIterator[T, V any](in iter.Seq2[T, V]) *IterableSequence2[T, V]

Chain2 is used to add a third type to the chain; e.g. to map to an unrelated type.

func (*IterableSequence2[T, V]) All

func (iter *IterableSequence2[T, V]) All(predicateFunc func(T, V) bool) bool

func (*IterableSequence2[T, V]) Any

func (iter *IterableSequence2[T, V]) Any(predicateFunc func(T, V) bool) bool

func (*IterableSequence2[T, V]) Count

func (iter *IterableSequence2[T, V]) Count() int

func (*IterableSequence2[T, V]) Each

func (iter *IterableSequence2[T, V]) Each() func(func(T, V) bool)

Each is the final point to get a two-item iterator out of an IterableSequence2. After chaining your various .Map(...).Filter(..)... do a `range .Each()` to iterate over it in your code.

func (*IterableSequence2[T, V]) Filter

func (iter *IterableSequence2[T, V]) Filter(filterFunc func(T, V) bool) *IterableSequence2[T, V]

func (*IterableSequence2[T, V]) FirstVal

func (iter *IterableSequence2[T, V]) FirstVal() *IterableSequence[T]

FirstVal turns the 2-value iter into a 1-value iter, using the first

func (*IterableSequence2[T, V]) Map

func (iter *IterableSequence2[T, V]) Map(mapFunc func(T, V) V) *IterableSequence[V]

Map is the classic function map -- takes a function, applies it to each item in the iterator, and yields that result

func (*IterableSequence2[T, V]) SecondVal

func (iter *IterableSequence2[T, V]) SecondVal() *IterableSequence[V]

SecondVal turns the 2-value iter into a 1-value iter, using the second

func (*IterableSequence2[T, V]) Tap

func (iter *IterableSequence2[T, V]) Tap(visitor func(T, V)) *IterableSequence2[T, V]

Tap is a borrowed Rubyism -- it takes each item and passes it along, but feeds it to a function to visit first. Useful for calling methods, sanitizing fields, etc.

type IterableSequenceJunction

type IterableSequenceJunction[T any, V comparable] struct {
	// contains filtered or unexported fields
}

IterableSequenceJunction is an opaque wrapper on an iterator to allow for chained methods, useful when going from one type to another like doing a .Map from int to string.

func ChainJunction

func ChainJunction[T any, V comparable](in *IterableSequence[T]) *IterableSequenceJunction[T, V]

ChainJunction is used to go from a single-type chain to a dual-type chain. This conversion is needed is doing a Map/Reduce that converts type.

func ChainJunctionFromIterator

func ChainJunctionFromIterator[T any, V comparable](inFunc func(func(T) bool)) *IterableSequenceJunction[T, V]

ChainJunctionFromIterator creates an chainable IterableSequence2 from an existing iterator.

func ChainJunctionFromSlice

func ChainJunctionFromSlice[T any, V comparable](in []T) *IterableSequenceJunction[T, V]

ChainJunctionFromSlice creates an chainable IterableSequence2 from an existing slice.

func (*IterableSequenceJunction[T, V]) Chain

func (iter *IterableSequenceJunction[T, V]) Chain() *IterableSequence[T]

func (*IterableSequenceJunction[T, V]) GroupBy

func (iter *IterableSequenceJunction[T, V]) GroupBy(keyFunc func(T) V) *IterableSequence2[V, *IterableSequence[T]]

func (*IterableSequenceJunction[T, V]) Map

func (iter *IterableSequenceJunction[T, V]) Map(mapFunc func(T) V) *IterableSequence[V]

func (*IterableSequenceJunction[T, V]) Reduce

func (iter *IterableSequenceJunction[T, V]) Reduce(reduceFunc func(V, T) V) V

func (*IterableSequenceJunction[T, V]) ReduceWithZero

func (iter *IterableSequenceJunction[T, V]) ReduceWithZero(reduceFunc func(V, T) V, zeroValue V) V

func (*IterableSequenceJunction[T, V]) Slice

func (iter *IterableSequenceJunction[T, V]) Slice() []T

func (*IterableSequenceJunction[T, V]) Zip

func (iter *IterableSequenceJunction[T, V]) Zip(i *IterableSequence[V]) iter.Seq2[T, V]

type IterableSequenceJunction2

type IterableSequenceJunction2[T any, V any, K comparable] struct {
	// contains filtered or unexported fields
}

IterableSequenceJunction is an opaque wrapper on a two-item iterator to allow for chained methods, useful when going from one type to another like doing a .Map from int to string.

func ChainJunction2

func ChainJunction2[T any, V, K comparable](in *IterableSequence2[T, V]) *IterableSequenceJunction2[T, V, K]

ChainJunction2 is used to add a third type to the chain; e.g. to map to an unrelated type.

func (*IterableSequenceJunction2[T, V, K]) Chain

func (iter *IterableSequenceJunction2[T, V, K]) Chain() *IterableSequence2[T, V]

func (*IterableSequenceJunction2[T, V, K]) Map

func (iter *IterableSequenceJunction2[T, V, K]) Map(mapFunc func(T, V) K) *IterableSequence[K]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL