iter

package
v3.7.0 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2024 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package iter defines an iterator interface, a collection of concrete iterator types, and some functions for operating on iterators. It is also a drop-in replacement for the Go 1.23 standard library package iter (a preview of which is available in Go 1.22 when building with GOEXPERIMENT=rangefunc).

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

func Page[F ~func(S, bool) error, S ~[]T, T any](inp Of[T], pageSize int, f F) 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/v3/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[F ~func(T, T) T, T any](inp Of[T], f F) Of[T]

Accum accumulates the result of repeatedly applying a simple 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/v3/iter"
)

func main() {
	var (
		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 { return a + b })
	)
	for sums.Next() {
		fmt.Println(sums.Val())
	}
	if err := sums.Err(); err != nil {
		panic(err)
	}
}
Output:

1
3
6
10
15

func Accumx

func Accumx[F ~func(T, T) (T, error), T any](inp Of[T], f F) Of[T]

Accumx is the extended form of Accum. It 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])

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/v3/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[F ~func(T) bool, T any](inp Of[T], f F) 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) 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[M ~map[K]V, K comparable, V any](m M) Of[Pair[K, V]]

FromMap produces an iterator of key-value pairs from a Go map. The resulting iterator never returns an error. Note that this is implemented in terms of FromMapKeys, which makes copies the keys of the map to a new slice.

Example
package main

import (
	"fmt"

	"github.com/bobg/go-generics/v3/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

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

FromMapKeys produces an iterator over the keys of a Go map. Note that this is implemented in terms of FromSlice, after first copying the keys of the map to a new slice.

func FromSeq added in v3.4.0

func FromSeq[T any](seq Seq[T]) Of[T]

FromSeq converts a Go 1.23 iterator into an Of[T].

func FromSeq2 added in v3.4.0

func FromSeq2[T, U any](seq Seq2[T, U]) Of[Pair[T, U]]

FromSeq2 converts a Go 1.23 pair iterator into an Of[Pair[T, U]].

func FromSeq2Context added in v3.4.0

func FromSeq2Context[T, U any](ctx context.Context, seq Seq2[T, U]) Of[Pair[T, U]]

FromSeq2Context converts a Go 1.23 pair iterator into an Of[Pair[T, U]].

func FromSeqContext added in v3.4.0

func FromSeqContext[T any](ctx context.Context, seq Seq[T]) Of[T]

FromSeqContext converts a Go 1.23 iterator into an Of[T].

func FromSlice

func FromSlice[S ~[]T, T any](s S) Of[T]

FromSlice creates an iterator over the elements of a slice.

func Gen

func Gen[F ~func() (T, bool, error), T any](f F) 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[F ~func(chan<- T) error, T any](f F) 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 (
	"fmt"

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

func main() {
	it := iter.Go(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

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 LongLines added in v3.3.0

func LongLines(ctx context.Context, r io.Reader) Of[io.Reader]

LongLines produces an iterator of readers, each delivering a single line of text from r. Unlike Lines, this does not use a bufio.Scanner and is not subject to its default line-length limit. Each reader must be fully consumed before the next one is available. If not consuming all readers from the iterator, the caller should cancel the context to reclaim resources.

func Map

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

Map produces an iterator of values transformed from an input iterator by a simple mapping function.

func Mapx

func Mapx[F ~func(T) (U, error), T, U any](inp Of[T], f F) Of[U]

Mapx is the extended form of Map. It 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 Prepared added in v3.1.0

func Prepared[T any](ctx context.Context, stmt *sql.Stmt, args ...any) (Of[T], error)

Prepared is like SQL but uses a prepared sql.Stmt instead of a database and string query. It is the caller's responsibility to close the statement.

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.

If the query produces a single value per row, T may be any scalar type (bool, int, float, string) into which the values can be scanned.

Otherwise 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[F ~func(T) bool, T any](inp Of[T], f F) 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/v3/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

type Option func(*chanIterConf)

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

func WithContext

func WithContext(ctx context.Context) Option

WithContext associates a context option with a channel iterator.

func WithError

func WithError(f func() error) Option

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).

type Seq added in v3.2.0

type Seq[V any] func(yield func(V) bool)

Seq is a Go 1.23 iterator over sequences of individual values. When called as seq(yield), seq calls yield(v) for each value v in the sequence, stopping early if yield returns false.

This type is defined in the same way as in the standard library, but is not identical, because Go type aliases cannot (yet?) be used with generic types.

func All added in v3.2.0

func All[T any](inp Of[T]) Seq[T]

All makes a Go 1.23 iterator from an Of[T], suitable for use in a one-variable for-range loop. To try this in Go 1.22, build with the environment variable GOEXPERIMENT set to rangefunc. See https://go.dev/wiki/RangefuncExperiment.

The caller should still check the iterator's Err method after the loop terminates.

type Seq2 added in v3.2.0

type Seq2[K, V any] func(yield func(K, V) bool)

Seq2 is a Go 1.23 iterator over sequences of pairs of values, most commonly key-value pairs. When called as seq(yield), seq calls yield(k, v) for each pair (k, v) in the sequence, stopping early if yield returns false.

This type is defined in the same way as in the standard library, but is not identical, because Go type aliases cannot (yet?) be used with generic types.

func AllCount added in v3.2.0

func AllCount[T any](inp Of[T]) Seq2[int, T]

AllCount makes a Go 1.23 counting iterator from an Of[T], suitable for use in a two-variable for-range loop. To try this in Go 1.22, build with the environment variable GOEXPERIMENT set to rangefunc. See https://go.dev/wiki/RangefuncExperiment.

The caller should still check the iterator's Err method after the loop terminates.

func AllPairs added in v3.2.0

func AllPairs[T, U any](inp Of[Pair[T, U]]) Seq2[T, U]

AllPairs makes a Go 1.23 pair iterator from an Of[Pair[T, U]], suitable for use in a two-variable for-range loop. To try this in Go 1.22, build with the environment variable GOEXPERIMENT set to rangefunc. See https://go.dev/wiki/RangefuncExperiment.

The caller should still check the iterator's Err method after the loop terminates.

Jump to

Keyboard shortcuts

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