iter

package module
v3.0.0-alpha Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2023 License: BSD-3-Clause Imports: 5 Imported by: 0

README

iter

Package iter provides generic, lazy iterators, functions for producing them from primitive types, as well as functions and methods for transforming and consuming them.

Usage

package main

import (
	"fmt"
	"strings"

	"mtoohey.com/iter/v3"
)

func main() {
	initial := iter.Elems([]string{"hello", "beautiful", "world"})
	result := initial.Filter(func(s string) bool {
		return len(s) < 6
	}).Map(strings.ToUpper).Collect()
	fmt.Println(result) // produces: [HELLO WORLD]
}

Regarding Performance

There is some overhead to using the iterators in this package, since each evaluation requires a function call, so if the performance of your application is a top priority, this package might not be the best choice. Don't guess about performance though: I would recommend benchmarking to determine the impact of using iterators, because in some cases, lazy iterators may be faster than the equivalent strict loop.

Acknowledgements

Documentation

Overview

Package iter provides generic, lazy iterators, functions for producing them from primitive types, as well as functions and methods for transforming and consuming them.

When reading the documentation of the functions contained in this package, you should assume that any function which accepts an iterator, but does not return one, consumes it unless otherwise stated, meaning that the values contained within cannot be used again.

It might seem as though this package's API contains some duplicate functionality, since there are many functions that appear to do the same thing as methods of the same names defined on Iter[T]. However, there is an important difference between these functions and their method counterparts. Since Go does not support type parameters on methods, (Iter[T]).Map can only return Iter[T] (an iterator of the same type as the input iterator). Map does not have this limitation; it can map from an Iter[T] to an Iter[U] (an iterator with a different type than the input iterator). The method versions are still provided even though their functionality is a strict subset of that of the function versions because using methods when possible results in more readable code.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindMap

func FindMap[T, U any](i Iter[T], f func(T) (U, error)) (U, bool)

FindMap returns the first transformed value in the iterator for which the provided function does not return an error. As with Find, it consumes all values up to the first passing one.

func Fold

func Fold[T, U any](i Iter[T], init U, f func(curr U, next T) U) U

Fold repeatedly applies the provided function to the current value (starting with init) and the next value of the iterator, until the whole iterator is consumed.

func Max

func Max[T constraints.Ordered](oi Iter[T]) (T, bool)

Max returns the maximum value in the provided iterator.

func MaxByKey

func MaxByKey[T any, U constraints.Ordered](i Iter[T], key func(T) U) (T, bool)

MaxByKey returns the value with the maximum result after the application of the provided function.

func Min

func Min[T constraints.Ordered](oi Iter[T]) (T, bool)

Min returns the minimum value in the provided iterator.

func MinByKey

func MinByKey[T any, U constraints.Ordered](i Iter[T], key func(T) U) (T, bool)

MinByKey returns the value with the minimum result after the application of the provided function.

func Sum

func Sum[T constraints.Ordered](oi Iter[T]) T

Sum returns the sum of all the values in the provided iterator.

func TryFold

func TryFold[T, U any](i Iter[T], init U, f func(curr U, next T) (U, error)) (U, error)

TryFold applies the provided fallible function to the current value (starting with init) and the next value of the iterator, until the whole iterator is consumed. If at any point an error is returned, the operation stops and that error is returned.

func Unzip

func Unzip[T, U any](i Iter[tuple.T2[T, U]]) (Iter[T], Iter[U])

Unzip returns two iterators, one yielding the left values of the tuples yielded by the input iterator, the other yielding the right values of the tuples. Note that, while the input iterator is evaluated lazily, exceptionally inequal consumption of the left vs the right iterator can lead to high memory consumption by values cached for the other iterator.

Types

type Iter

type Iter[T any] func() (T, bool)

Iter is a generic iterator function, the basis of this whole package. Note that the typical iter.Next() method is replaced with iter(), since Iter is simply defined as func() (T, bool).

func Elems

func Elems[T any](s []T) Iter[T]

Elems returns an iterator over the values of the provided slice.

func Empty

func Empty[T any]() Iter[T]

Empty returns an iterator that yields no values.

func Enumerate

func Enumerate[T any](i Iter[T]) Iter[tuple.T2[int, T]]

Enumerate returns an iterator of tuples indices and values from the input iterator.

func FilterMap

func FilterMap[T, U any](i Iter[T], f func(T) (U, error)) Iter[U]

FilterMap returns a new iterator that yields the mapped values which are produced without errors from the provided function.

func FlatMap

func FlatMap[T, U any](i Iter[T], f func(T) Iter[U]) Iter[U]

FlatMap returns a new iterator that yields the values produced by iterators returned by the provided function when it is applied to values from the input iterator.

func GenWhile

func GenWhile[T any](f func() (T, error)) Iter[T]

GenWhile returns an iterator that yields return values from the provided function while it does not produce errors. After the first error, no more values are yielded.

func GroupBy

func GroupBy[K comparable, V any](i Iter[V], f func(value V) (key K)) Iter[tuple.T2[K, Iter[V]]]

GroupBy returns a new iterator which yields tuples whose first field is a key returned by f, and whose second field is a sub-iterator yielding a group of consecutive values from the input iterator for which f returned the key in the first field.

func Ints

func Ints[T constraints.Integer]() Iter[T]

Ints returns an iterator that produces constraints.Integer values of the specified generic type, starting from 0 and increasing by 1.

func IntsBy

func IntsBy[T constraints.Integer](by T) Iter[T]

IntsBy returns an iterator that produces constraints.Integer values of the specified generic type, starting from 0 and increasing by the provided value.

func IntsFrom

func IntsFrom[T constraints.Integer](start T) Iter[T]

IntsFrom returns an iterator that produces constraints.Integer values of the specified generic type, starting from the provided value and increasing by 1.

func IntsFromBy

func IntsFromBy[T constraints.Integer](start T, by T) Iter[T]

IntsFromBy returns an iterator that produces constraints.Integer values of the specified generic type, starting from, and increasing by the provided values.

func KVZipLazy

func KVZipLazy[T comparable, U any](m map[T]U) Iter[tuple.T2[T, U]]

KVZipLazy returns an iterator that yields tuples of the input map's keys and values. This function uses a channel and a goroutine to manage key values lazily. Warning: if you don't consume the whole iterator, you will end up leaking a goroutine: https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html. Unless you're dealing with large maps where strict evaluation of keys may be problematic, KVZipStrict is recommended.

func KVZipStrict

func KVZipStrict[T comparable, U any](m map[T]U) Iter[tuple.T2[T, U]]

KVZipStrict returns an iterator that yields tuples of the input map's keys and values. While the value lookup occurs lazily, the keys must be accumulated immediately when the iterator is created, so this operation can be expensive for large maps. If this is a problem, see KVZipLazy.

func Map

func Map[T, U any](i Iter[T], f func(T) U) Iter[U]

Map returns a new iterator that yields the results of applying the provided function to the input iterator.

func MapWhile

func MapWhile[T, U any](i Iter[T], f func(T) (U, error)) Iter[U]

MapWhile returns a new iterator that yields the values produced by applying the provided function to the values of the input iterator, until the first error occurs. At that point, no further values are returned.

func Receive

func Receive[T any](ch <-chan T) Iter[T]

Receive returns an iterator that reads values from the provided channel, and is exhausted when the channel is closed. Note that since this iterator reads from a channel, every time the next value is requested the program may end up deadlocking if values have not been written: the same rules apply as those for reading from a channel in the usual manner.

func Runes

func Runes(s string) Iter[rune]

Runes returns an iterator over the runes of the input string. Runes(s).Collect() should be equivalent to []rune(s).

func Seqs

func Seqs[T any](i Iter[T], n uint) Iter[[]T]

Seqs returns an iterator over slices of length n+1 containing first items 0 through n of the input iterator, then items 1 through n+1, etc.

func SplitByRune

func SplitByRune(s string, r rune) Iter[string]

SplitByRune returns an iterator over the substrings of the input string between occurrences of the provided rune. SplitByRune(s, r).Collect() should be equivalent to strings.Split(s, string(r)) for valid runes.

func SplitByString

func SplitByString(s string, sep string) Iter[string]

SplitByString returns an iterator over the substrings of the input string between occurrences of the provided separator string. SplitByString(s, sep).Collect() should be equivalent to strings.Split(s, sep).

func Zip

func Zip[T, U any](a Iter[T], b Iter[U]) Iter[tuple.T2[T, U]]

Zip returns an iterator that yields tuples of the two provided input iterators.

func (Iter[T]) All

func (i Iter[T]) All(f func(T) bool) bool

All returns whether all values of the iterator satisfy the provided predicate function.

func (Iter[T]) Any

func (i Iter[T]) Any(f func(T) bool) bool

Any returns whether any of the values of the iterator satisfy the provided predicate function.

func (Iter[T]) Chain

func (i Iter[T]) Chain(o Iter[T]) Iter[T]

Chain returns a new iterator that first consumes the first iterator, then the second.

func (Iter[T]) Collect

func (i Iter[T]) Collect() []T

Collect fetches the next value of the iterator until no more values are found, places these values in a slice, and returns it. Note that since Collect does not know how many values it will find, it must resize the slice multiple times during the collection process. This can result in poor performance, so CollectInto should be used when possible.

func (Iter[T]) CollectInto

func (i Iter[T]) CollectInto(buf []T) int

CollectInto inserts values yielded by the input iterator into the provided slice, and returns the number of values it was able to add before the iterator was exhausted or the slice was full.

func (Iter[T]) Consume

func (i Iter[T]) Consume()

Consume fetches the next value of the iterator until no more values are found. Note that it doesn't do anything with the values that are produced, but it can be useful in certain cases, such dropping a fixed number of items from an iterator by chaining Take and Consume.

func (Iter[T]) Count

func (i Iter[T]) Count() int

Count returns the number of remaining values in the iterator.

func (Iter[T]) Cycle

func (i Iter[T]) Cycle() (Iter[T], bool)

Cycle creates an iterator that first consumes the provided input iterator, then repeatedly returns the prior values. The second return value is true if the input iterator was non-empty (meaning the first return value is an infinite iterator) or false otherwise (meaning the first return value is nil).

func (Iter[T]) Filter

func (i Iter[T]) Filter(f func(T) bool) Iter[T]

Filter returns a new iterator that only yields the values in the input iterator that satisfy the provided function.

func (Iter[T]) FilterMap

func (i Iter[T]) FilterMap(f func(T) (T, error)) Iter[T]

FilterMap returns a new iterator that yields the mapped values which are produced without errors from the provided function.

func (Iter[T]) Find

func (i Iter[T]) Find(f func(T) bool) (T, bool)

Find returns the first value in the iterator that satisfies the provided predicate function, as well as a boolean indicating whether any value was found. It consumes all values up to the first satisfactory value, or the whole iterator if no values satisfy the predicate.

func (Iter[T]) FindMap

func (i Iter[T]) FindMap(f func(T) (T, error)) (T, bool)

FindMap returns the first transformed value in the iterator for which the provided function does not return an error. As with Find, it consumes all values up to the first passing one.

func (Iter[T]) FlatMap

func (i Iter[T]) FlatMap(f func(T) Iter[T]) Iter[T]

FlatMap returns a new iterator that yields the values produced by iterators returned by the provided function when it is applied to values from the input iterator.

func (Iter[T]) Fold

func (i Iter[T]) Fold(init T, f func(curr T, next T) T) T

Fold repeatedly applies the provided function to the current value (starting with init) and the next value of the iterator, until the whole iterator is consumed.

func (Iter[T]) ForEach

func (i Iter[T]) ForEach(f func(T))

ForEach applies the provided function to all remaining values in the current iterator.

func (Iter[T]) ForEachParallel

func (i Iter[T]) ForEachParallel(f func(T))

ForEachParallel applies the provided function to all remaining values in the current iterator. It differs from ForEach in that, where ForEach runs on a single thread and waits for each execution of the function to complete before fetching the next value and calling the function again, ForEachParallel performs executions of the function on different threads and only waits for all executions at the end. When the function to be executed is expensive and the order in which values of the iterator are operated upon does not matter, this method can result in better performance than ForEach.

func (Iter[T]) Inspect

func (i Iter[T]) Inspect(f func(T)) Iter[T]

Inspect produces an iterator with identical values as the input iterator, but it applies the provided function to values of the iterator as they are requested. This method differs from ForEach in that it is lazy, whereas ForEach is not, and it returns an iterator, while ForEach does not.

func (Iter[T]) Last

func (i Iter[T]) Last() (T, bool)

Last returns the final value of the iterator, along with a boolean indicating whether the operation was successful, in other words, whether the input iterator was non-empty.

func (Iter[T]) Map

func (i Iter[T]) Map(f func(T) T) Iter[T]

Map returns a new iterator that yields the results of applying the provided function to the input iterator.

func (Iter[T]) MapWhile

func (i Iter[T]) MapWhile(f func(T) (T, error)) Iter[T]

MapWhile returns a new iterator that yields the values produced by applying the provided function to the values of the input iterator, until the first error occurs. At that point, no further values are returned.

func (Iter[T]) Mutex

func (i Iter[T]) Mutex() Iter[T]

Mutex returns a new iterator that uses a mutex to prevent multiple simultaneous evaluations of the wrapped iterator. This method should be the final method called on an iterator before it is used across multiple goroutines, as other methods are not guaranteed to be behave correctly when multiple evaluations occur simultaneously.

func (Iter[T]) Nth

func (i Iter[T]) Nth(n int) (T, bool)

Nth returns the nth value in the iterator, and a boolean indicating whether the iterator was too short. The provided value of n should be non-negative.

func (Iter[T]) Partition

func (i Iter[T]) Partition(f func(T) bool) (Iter[T], Iter[T])

Partition returns two iterators, one containing the values of the original iterator that satisfy the provided function, the other containing the values that do not.

func (Iter[T]) Pos

func (i Iter[T]) Pos(f func(T) bool) int

Pos returns the index of the first element satisfying the provided function, or -1 if one is not found. It consumes every element up to and including the element that satisfies the function, or the whole iterator if no no satisfactory element is found.

func (Iter[T]) Reduce

func (i Iter[T]) Reduce(f func(curr T, next T) T) (T, bool)

Reduce repeatedly applies the provided function to the current value (starting with iterator's first value) and the next value of the iterator, until the whole iterator is consumed. The second return value is true if the input iterator was non-empty, in which case the first return value is the result of the final application of f (or just the first element of the input if there was only one element). Otherwise, if the input iterator is empty, the second return value is false and the first is the zero value.

func (Iter[T]) Rev

func (i Iter[T]) Rev() Iter[T]

Rev produces a new iterator whose values are reversed from those of the input iterator. Note that this method is not lazy, it must consume the whole input iterator immediately to produce the reversed result.

func (Iter[T]) Send

func (i Iter[T]) Send(ch chan<- T)

Send consumes the input iterator, sending all yielded values into the provided channel. As with receive, this can result in deadlocks if used improperly: if nobody is reading from the channel. Also note that this method does not close the value after the values have been written, if you want that to happen, you should do so yourself.

func (Iter[T]) Skipping

func (i Iter[T]) Skipping(n uint) Iter[T]

Skipping returns a new iterator that returns every n+1'th value of the input iterator.

func (Iter[T]) Take

func (i Iter[T]) Take(n uint) Iter[T]

Take returns an iterator that limits that yields up to (but no more than) n values from the input iterator.

func (Iter[T]) TakeWhile

func (i Iter[T]) TakeWhile(f func(T) bool) Iter[T]

TakeWhile produces a new iterator that yields values from the input iterator while those values satisfy the provided function. Once the first failure occurs, no more values are yielded. If this occurs, the previously yielded values, as well as the first failing value, are consumed from the input iterator.

func (Iter[T]) TryFold

func (i Iter[T]) TryFold(init T, f func(curr T, next T) (T, error)) (T, error)

TryFold applies the provided fallible function to the current value (starting with init) and the next value of the iterator, until the whole iterator is consumed. If at any point an error is returned, the operation stops and that error is returned.

func (Iter[T]) TryForEach

func (i Iter[T]) TryForEach(f func(T) error) error

TryForEach applies the provided fallible function to all remaining values in the current iterator, but stops if an error is returned at any point.

Directories

Path Synopsis
_demos
eratosthenes
eratosthenes provides an example of how the laziness of iter.Elems allows us to mutate the slice's values after creating the iterator.
eratosthenes provides an example of how the laziness of iter.Elems allows us to mutate the slice's values after creating the iterator.
first-subdir-executable
first-subdir-executable finds the first file executable by any user located in a subdirectory of the provided directory.
first-subdir-executable finds the first file executable by any user located in a subdirectory of the provided directory.
lazy-eratosthenes
lazy-eratosthenes demonstrates how to construct an infinite, lazy, prime sieve using iterators.
lazy-eratosthenes demonstrates how to construct an infinite, lazy, prime sieve using iterators.
internal

Jump to

Keyboard shortcuts

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