iter

package
v1.7.2 Latest Latest
Warning

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

Go to latest
Published: Jan 31, 2023 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package iter defines an iterator interface, a collection of concrete iterator types, and some functions for operating on iterators.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func LastN

func LastN[T any](inp Of[T], n int) ([]T, error)

LastN produces a slice containing the last n elements of the input iterator (or all of the input, if there are fewer than n elements). There is no guarantee that any elements will ever be produced: the input iterator may be infinite!

func Page added in v0.2.0

func Page[T any](inp Of[T], pageSize int, f func([]T, bool) error) error

Page consumes inp one "page" at a time of up to pageSize elements, repeatedly calling a callback with a slice of the items consumed. The callback also gets a second argument that is false until the final call, when it is true.

An error from the callback will terminate Page and return that error.

The space for the slice is reused on each call to the callback.

The slice in every non-final call of the callback is guaranteed to have a length of pageSize. The final call of the callback may contain an empty slice.

Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	var (
		ints    = iter.Ints(1, 1)       // All integers starting at 1
		first10 = iter.FirstN(ints, 10) // First 10 integers
	)
	err := iter.Page(first10, 3, func(page []int, final bool) error {
		fmt.Println(page, final)
		return nil
	})
	if err != nil {
		panic(err)
	}
}
Output:

[1 2 3] false
[4 5 6] false
[7 8 9] false
[10] true

func ToChan

func ToChan[T any](inp Of[T]) (<-chan T, func() error)

ToChan creates a Go channel and copies the contents of an iterator to it. The second return value is a function that may be called after the channel is closed to inspect any error that occurred.

func ToChanContext

func ToChanContext[T any](ctx context.Context, inp Of[T]) (<-chan T, func() error)

ToChanContext creates a Go channel and copies the contents of an iterator to it. The second return value is a function that may be called after the channel is closed to inspect any error that occurred. The channel will close early if the context is canceled (and the error-returning function will indicate that).

func ToMap

func ToMap[K comparable, V any](inp Of[Pair[K, V]]) (map[K]V, error)

ToMap consumes an iterator of key-value pairs and produces a Go map of the values. All but the last of any pairs with duplicate keys are discarded. Be careful! The input may be very long or even infinite. Consider using FirstN to ensure the input has a reasonable size.

func ToSlice

func ToSlice[T any](iter Of[T]) ([]T, error)

ToSlice consumes the elements of an iterator and returns them as a slice. Be careful! The input may be very long or even infinite. Consider using FirstN to ensure the input has a reasonable size.

Types

type Of

type Of[T any] interface {
	// Next advances the iterator to its next value and tells whether one is available to read.
	// A true result is necessary before calling Val.
	// Once Next returns false, it must continue returning false.
	Next() bool

	// Val returns the current value of the iterator.
	// Callers must get a true result from Next before calling Val.
	// Repeated calls to Val
	// with no intervening call to Next
	// should return the same value.
	Val() T

	// Err returns the error that this iterator's source encountered during iteration, if any.
	// It may be called only after Next returns false.
	Err() error
}

Of is the interface implemented by iterators. It is called "Of" so that when qualified with this package name and instantiated with a member type, it reads naturally: e.g., iter.Of[int].

func Accum

func Accum[T any](inp Of[T], f func(T, T) (T, error)) Of[T]

Accum accumulates the result of repeatedly applying a function to the elements of an iterator. If inp[i] is the ith element of the input and out[i] is the ith element of the output, then:

out[0] == inp[0]

and

out[i+1] == f(out[i], inp[i+1])
Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	ints := iter.Ints(1, 1)        // All integers starting at 1
	first5 := iter.FirstN(ints, 5) // First 5 integers
	sums := iter.Accum(first5, func(a, b int) (int, error) { return a + b, nil })
	for sums.Next() {
		fmt.Println(sums.Val())
	}
	if err := sums.Err(); err != nil {
		panic(err)
	}
}
Output:

1
3
6
10
15

func Combinations added in v1.6.0

func Combinations[T any](ctx context.Context, s []T, n int) Of[[]T]

Combinations produces an iterator over all n-length combinations of distinct elements from s.

If s is [1 2 3] and n is 2, this function will produce:

[1 2] [1 3] [2 3]

func CombinationsWithReplacement added in v1.6.0

func CombinationsWithReplacement[T any](ctx context.Context, s []T, n int) Of[[]T]

CombinationsWithReplacement produces an iterator over all n-length combinations of possibly repeated elements from s.

If s is [1 2 3] and n is 2, this function will produce:

[1 1] [1 2] [1 3] [2 2] [2 3] [3 3]

func Concat

func Concat[T any](inps ...Of[T]) Of[T]

Concat concatenates the members of the input iterators.

func Dup

func Dup[T any](inp Of[T], n int) []Of[T]

Dup duplicates the contents of an iterator, producing n new iterators, each containing the members of the original.

An internal buffer grows to roughly the size of the difference between the output iterator that is farthest ahead in the stream, and the one that is farthest behind.

Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	var (
		ints    = iter.Ints(1, 1)       // All integers starting at 1
		first10 = iter.FirstN(ints, 10) // First 10 integers
		dups    = iter.Dup(first10, 2)  // Two copies of the first10 iterator
		evens   = iter.Filter(dups[0], func(val int) bool { return val%2 == 0 })
		odds    = iter.Filter(dups[1], func(val int) bool { return val%2 == 1 })
	)
	evensSlice, err := iter.ToSlice(evens)
	if err != nil {
		panic(err)
	}
	fmt.Println(evensSlice)
	oddsSlice, err := iter.ToSlice(odds)
	if err != nil {
		panic(err)
	}
	fmt.Println(oddsSlice)
}
Output:

[2 4 6 8 10]
[1 3 5 7 9]

func Filter

func Filter[T any](inp Of[T], f func(T) bool) Of[T]

Filter copies the input iterator to the output, including only those elements that cause f to return true.

func FirstN

func FirstN[T any](inp Of[T], n int) Of[T]

FirstN produces an iterator containing the first n elements of the input (or all of the input, if there are fewer than n elements). Remaining elements of the input are not consumed. It is the caller's responsibility to release any associated resources.

func From

func From[T any](items ...T) Of[T]

From creates an iterator over the given items.

func FromChan

func FromChan[T any](ch <-chan T, opts ...Option[T]) Of[T]

FromChan copies a Go channel to an iterator. If the WithContext option is given, copying will end early if the given context is canceled (and the iterator's Err function will indicate that). If the WithError option is given, it is called after the channel closes to determine the value of the iterator's Err function.

func FromMap

func FromMap[K comparable, V any](m map[K]V) Of[Pair[K, V]]

FromMap produces an iterator of key-value pairs from a Go map.

Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	m := map[string]int{
		"one":   1,
		"two":   2,
		"three": 3,
	}
	it := iter.FromMap(m)
	for it.Next() {
		val := it.Val()
		fmt.Println(val.X, val.Y)
	}
	if err := it.Err(); err != nil {
		panic(err)
	}
}
Output:

one 1
two 2
three 3

func FromMapKeys added in v0.6.0

func FromMapKeys[K comparable, V any](m map[K]V) Of[K]

FromMapKeys produces an iterator over the keys of a Go map.

func FromSlice

func FromSlice[T any](s []T) Of[T]

FromSlice creates an iterator over the elements of a slice.

func Gen

func Gen[T any](f func() (T, bool, error)) Of[T]

Gen produces an iterator of values obtained by repeatedly calling f. If f returns an error, iteration stops and the error is available via the iterator's Err method. Otherwise, each call to f should return a value and a true boolean. When f returns a false boolean, it signals the normal end of iteration.

func Go

func Go[T any](ctx context.Context, f func(ch chan<- T) error) Of[T]

Go runs a function in a goroutine and returns an iterator over the values it produces. The function receives a channel for producing values. The channel closes when the function exits. Any error produced by the function is the value of the iterator's Err method.

Example
package main

import (
	"context"
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	it := iter.Go(context.Background(), func(ch chan<- int) error {
		ch <- 1
		ch <- 2
		ch <- 3
		return nil
	})
	slice, err := iter.ToSlice(it)
	if err != nil {
		panic(err)
	}
	fmt.Println(slice)
}
Output:

[1 2 3]

func Ints

func Ints(start, delta int) Of[int]

Ints produces an infinite iterator over integers beginning at start, with each element increasing by delta.

func Lines added in v0.6.0

func Lines(r io.Reader) Of[string]

Lines produces an iterator over the lines of text in r. This uses a bufio.Scanner and is subject to its default line-length limit (see https://pkg.go.dev/bufio#pkg-constants).

func Map

func Map[T, U any](inp Of[T], f func(T) (U, error)) Of[U]

Map produces an iterator of values transformed from an input iterator by a mapping function. If the mapping function returns an error, iteration stops and the error is available via the output iterator's Err method.

func Permutations added in v1.6.0

func Permutations[T any](ctx context.Context, s []T) Of[[]T]

Permutations produces an iterator over all permutations of s. It uses Heap's Algorithm. See https://en.wikipedia.org/wiki/Heap%27s_algorithm.

If s is [1 2 3], this function will produce:

[1 2 3] [2 1 3] [3 1 2] [1 3 2] [2 3 1] [3 2 1]

func Repeat

func Repeat[T any](val T) Of[T]

Repeat produces an infinite iterator repeatedly containing the given value.

func SQL

func SQL[T any](ctx context.Context, db QueryerContext, query string, args ...any) (Of[T], error)

SQL performs a query against db and returns the results as an iterator of type T. T must be a struct type whose fields have the same types, in the same order, as the values being queried. The values produced by the iterator will be instances of that struct type, with fields populated by the queried values.

func SkipN

func SkipN[T any](inp Of[T], n int) Of[T]

SkipN copies the input iterator to the output, skipping the first N elements.

func SkipUntil

func SkipUntil[T any](inp Of[T], f func(T) bool) Of[T]

SkipUntil copies the input iterator to the output, discarding the initial elements until the first one that causes f to return true. That element and the remaining elements of inp are included in the output, and f is not called again.

func Zip

func Zip[T, U any](t Of[T], u Of[U]) Of[Pair[T, U]]

Zip takes two iterators and produces a new iterator containing pairs of corresponding elements. If one input iterator ends before the other, Zip produces zero values of the appropriate type in constructing pairs.

Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/iter"
)

func main() {
	var (
		letters = iter.FromSlice([]string{"a", "b", "c", "d"})
		nums    = iter.FromSlice([]int{1, 2, 3})
		pairs   = iter.Zip(letters, nums)
	)
	for pairs.Next() {
		val := pairs.Val()
		fmt.Println(val.X, val.Y)
	}
	if err := pairs.Err(); err != nil {
		panic(err)
	}
}
Output:

a 1
b 2
c 3
d 0

type Option added in v0.3.0

type Option[T any] func(*chanIter[T])

Option is the type of options that can be passed to FromChan.

func WithContext added in v0.3.0

func WithContext[T any](ctx context.Context) Option[T]

WithContext associates a context option with a channel iterator.

func WithError added in v0.3.0

func WithError[T any](f func() error) Option[T]

WithError tells a channel iterator how to compute its Err value after its channel closes.

type Pair

type Pair[T, U any] struct {
	X T
	Y U
}

Pair is a simple generic pair struct.

type QueryerContext

type QueryerContext interface {
	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
}

QueryerContext is a minimal interface satisfied by *sql.DB (from database/sql).

Jump to

Keyboard shortcuts

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