Categorygithub.com/patrickhuber/go-iter
modulepackage
0.5.3
Repository: https://github.com/patrickhuber/go-iter.git
Documentation: pkg.go.dev

# README

Iteration library in go

This package provides generic iterators and iterator transformations in go.

Iterators defer iteration execution by pushing iteration logic into the Next() function.

This package has a dependency on go-types for the Option[T any] type. Users of the iter module can utilize Result[T] to capture errors or perform transformations on slices that can contain errors.

Looping

Here are three ways to loop over an iterator

For Loop

A for loop has init, condition and post sections that can be used on an iterator.

rng := iter.Range(0, 10)
for op := rng.Next(); op.IsSome(); op = rng.Next() {
    // code in here
}

Async (calling range on a channel)

You can also loop over a channel created from an Iterator[T] using the iter.Async function. You can specify a context with the iter.WithContext[T] option. If no context is specified, context.Background() is used.

rng := iter.Range(0, 10)
for value := range iter.Async(rng) {
    // code in here
}

Specify a context

rng := iter.Range(0,10)
op := iter.WithContext[int](context.TODO())
for value := range iter.Async(rng, op){
    // code here
}

ForEach

ForEach uses an anonymous function to iterate over each item to the caller.

rng := iter.Range(0, 10)
iter.ForEach(rng, func(i int) {
    fmt.Print(" ")
    fmt.Print(i)
})
// prints:
//  0 1 2 3 4 5 6 7 8 9

ForEachIndex

ForEachIndex uses an anonymous function to iterate over each item and the index of that item to the caller.

rng := iter.Range(0, 10)
iter.ForEachIndex(rng, func(index int, i int) {
    if index > 0 {
        fmt.Print(" ")
    }
    fmt.Print(i)
})
// prints:
// 0 1 2 3 4 5 6 7 8 9

Range

The Range function creates an iterator over [begin..end) (inclusive begin, exclusive end)

rng := iter.Range(0, 10)
iter.ForEachIndex(rng, func(index int, i int) {
    if index > 0 {
        fmt.Print(" ")
    }
    fmt.Print(i)
})
// prints:
// 0 1 2 3 4 5 6 7 8 9

RangeWith

The RangeWith function creates an iterator over the range begin..end. The includeBegin and includeEnd flags control if the range is inclusive start and inclusive end.

rng := iter.RangeWith(false, 0, 10, true)
iter.ForEachIndex(rng, func(index int, i int) {
    if index > 0 {
        fmt.Print(" ")
    }
    fmt.Print(i)
})
// prints:
// 1 2 3 4 5 6 7 8 9 10

Repeat

Repeat returns an iterator that repeats the given element, count times

rep := iter.Repeat(10, 5)
iter.ForEachIndex(rng, func(index int, i int) {
    if index > 0 {
        fmt.Print(" ")
    }
    fmt.Print(i)
})
// prints:
// 10 10 10 10 10

Select

The Select function transforms an iterator of one type to an iterator of another type.

rng := iter.Range(0,10)
strRng := iter.Select(rng, strconv.Itoa)
iter.ForEachIndex(strRng, func(index int, s string){
    if index > 0{
        fmt.Print(" ")
    }
    fmt.Print("'%s'", s)
})
// prints : '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'

Where

The Where function removes items from an iterator using a predicate function.

rng := iter.Range(0,10)
even := func(i int){ return i % 2 == 0}
evens := iter.Where(rng, even)
iter.ForEachIndex(evens, func(index int, i int){
    if index > 0{
        fmt.Print(" ")
    }
    fmt.Print("%d", i)
})
// prints : 0 2 4 6 8

FromSlice

The FromSlice function returns a slice iterator over the given slice

slice := []int{1, 3, 5, 7, 9}
it := iter.FromSlice(slice)
iter.ForEachIndex(it, func(index int, i int){
    if index > 0{
        fmt.Print(" ")
    }
    fmt.Print("%d", i)
})
// prints 1 3 5 7 9

ToSlice

The ToSlice function returns a slice from the given iterator by iterating over all elements.

rng := iter.Range(0, 10)
slice := iter.ToSlice(rng)
fmt.Println(slice)
// prints : [0 1 2 3 4 5 6 7 8 9]

FromMap

The FromMap function returns an iterator over the given map. FromMap captures keys of the map in the first call to Next(). Subsequent calls to Next() track an index into the key slice to return the next key value pair. Each call to Next() returns an Option tuple of Key Value pairs.

m := map[string]int{"0":0, "1":1, "2":2, "3":3}
it := iter.FromMap(m)
fmt.Print("[ ")
iter.ForEachIndex(it, func(index int, tup types.Tuple2[string, int]){
    if index > 0{
        fmt.Print(", ")
    }    
    k, v := tup.Deconstruct()
    fmt.Print("'%s':%d", k, v)
})
fmt.Print(" ]")
// prints : [ '0':0, '1':1, '2':2, '3':3 ]

FromMapAsync

The FromMapAsync function returns an iterator over the given map using channels and the supplied context. FromMapAsync uses a go routine to iterate over the map and channels to capture the key value pair. The Next() function removes a tuple key, value from the channel.

m := map[string]int{"0":0, "1":1, "2":2, "3":3}
it := iter.FromMapAsync(m, context.Background())
fmt.Print("[ ")
iter.ForEachIndex(it, func(index int, tup types.Tuple2[string, int]){
    if index > 0{
        fmt.Print(", ")
    }    
    k, v := tup.Deconstruct()
    fmt.Print("'%s':%d", k, v)
})
fmt.Print(" ]")
// prints : [ '0':0, '1':1, '2':2, '3':3 ]

Count

The Count function returns the count of element in the iterator by iterating over all the elements.

expected := 10
rng := iter.Range(0, expected)
actual := iter.Count(rng)
if actual != expected {
    t.Fatalf("expected count of %d but found %d", expected, actual)
}

FromChannel

The FromChannel function returns an iterator over the given channel. A context can be specified in options for early termination.

ch := make(chan int)
go func(c chan int) {
    defer close(c)
    for i := 0; i < 10; i++ {
        ch <- i
    }
}(ch)
it := iter.FromChannel(ch)
iter.ForEach(it, func(i int) {
    fmt.Println(i)
})

First

First returns the first item in the sequence. If the sequence has no more items, First returns types.None[T]

sequence := iter.Range(15, 30)
first := iter.First(sequence)
switch op := first.(type) {
case types.Some[int]:
    fmt.Println(op.Value)
case types.None[int]:
    fmt.Println("none")
}
// prints 
// 15

FirstWhere

FirstWhere returns the first item in the sequence that matches the condition. If the sequence has no more items or no matches exist, First returns types.None[T]

sequence := iter.Range(15, 30)
first := iter.FirstWhere(sequence, func(i int)bool{ return i % 10 == 0})
switch op := first.(type) {
case types.Some[int]:
    fmt.Println(op.Value)
case types.None[int]:
    fmt.Println("none")
}
// prints
// 20

# Functions

Async returns a channel for the given iterator over the context.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
FromMap returns an iterator over the given map.
FromMapAsync returns a call to FromChannel with a channel created by iterating over the map in a go routine The context passed in is used to pass the WithContext chanel option to the FromChannel call.
No description provided by the author
New creates a new iterator from the list of items.
No description provided by the author
RangeWith emulates the '[' '(' and ')' ']' syntax used to show a range is inclusive or exclusive.
Repeat returns an iterator that repeats the given `element` `count` times.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
WithContext provides an context.Context for channel operations.
Zip combines the two iterators into a single iterator of type Tuple[T1, T2].

# Interfaces

Iterator defines a generic iterface for iterating over a sequence.

# Type aliases

No description provided by the author
No description provided by the author