xiter

package module
v0.0.0-...-03c6262 Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2025 License: Apache-2.0 Imports: 2 Imported by: 0

README

xiter - Extended Iterators for Go

License Go Reference Go Version Build Status

xiter is a powerful extension library for Go's standard iter package, providing a rich set of functional-style operations for working with sequences and key-value pairs in Go 1.22+.

Features

  • Comprehensive API: Over 40 functional operations for sequence manipulation
  • Type-safe: Full support for Go's generics throughout the API
  • Dual sequence support: Works with both single-element sequences (iter.Seq) and key-value pairs (iter.Seq2)
  • Lazy evaluation: All operations are lazily evaluated for optimal performance
  • Side-effect free: Most operations return new iterators without modifying the original data
  • Seamless integration: Drop-in compatibility with Go's standard iter package
  • Performance optimized: Minimal overhead and efficient implementations

Installation

go get github.com/go-board/xiter

Quick Start

package main

import (
	"fmt"
	"iter"
	"github.com/go-board/xiter"
)

func main() {
	// Generate a sequence of numbers from 0 to 9
	numbers := xiter.Range1(10)

	// Double each number
	doubled := xiter.Map(numbers, func(x int) int { return x * 2 })

	// Filter even numbers (which are all even after doubling)
	evenDoubles := xiter.Filter(doubled, func(x int) bool { return x%2 == 0 })

	// Sum the results
	sum := xiter.Fold(evenDoubles, 0, func(acc, x int) int { return acc + x })

	fmt.Printf("Sum of doubled numbers: %d\n", sum) // Output: 90

	// Working with key-value pairs
	pairs := xiter.FromFunc2(func() (string, int, bool) {
		// This would typically come from some data source
		staticPairs := []struct{ K string; V int }{"one": 1, "two": 2, "three": 3}
		index := 0
		return func() (string, int, bool) {
			if index >= len(staticPairs) {
				return "", 0, false
			}
			pair := staticPairs[index]
			index++
			return pair.K, pair.V, true
		}
	}())

	// Multiply values by 10
	enhanced := xiter.Map2(pairs, func(k string, v int) (string, int) {
		return k, v * 10
	})

	// Print all pairs
	xiter.ForEach2(enhanced, func(k string, v int) {
		fmt.Printf("%s: %d\n", k, v) // Outputs: one: 10, two: 20, three: 30
	})
}

Core Concepts

xiter provides operations for two main sequence types:

  • iter.Seq[E]: A sequence of elements of type E
  • iter.Seq2[K, V]: A sequence of key-value pairs of types K and V

All operations are designed to be chained together, creating a pipeline of transformations that are only executed when the sequence is consumed.

API Overview

Sequence Generation
// Create a sequence from 0 to 9
numbers := xiter.Range1(10)

// Create a sequence from 5 to 14
numbers := xiter.Range2(5, 15)

// Create a sequence from 1 to 10 with step 2
odds := xiter.Range3(1, 11, 2)

// Create a sequence from a function
count := 0
seq := xiter.FromFunc(func() (int, bool) {
    count++
    return count, count <= 5
})

// Create a sequence with a single element
one := xiter.Once(42)

// Create an empty sequence
empty := xiter.Empty[int]()

// Create an infinite sequence repeating a value
repeats := xiter.Repeat("hello")
Mapping
// Transform each element
numbers := xiter.Range1(5)
squares := xiter.Map(numbers, func(x int) int { return x * x })

// Transform while condition is true
doubles := xiter.MapWhile(numbers, func(x int) (int, bool) {
    result := x * 2
    return result, result < 10
})

// Transform key-value pairs
pairs := xiter.FromFunc2(func() (string, int, bool) {
    // ...
})
transformed := xiter.Map2(pairs, func(k string, v int) (string, int) {
    return "key_" + k, v * 10
})
Filtering
// Filter elements that satisfy a condition
numbers := xiter.Range1(10)
evens := xiter.Filter(numbers, func(x int) bool { return x%2 == 0 })

// Filter and map in a single step
strings := []string{"one", "two", "three"}
seq := xiter.FromFunc(func() (string, bool) {
    // ... (yield strings from slice)
})
longStrings := xiter.FilterMap(seq, func(s string) (string, bool) {
    if len(s) > 3 {
        return s, true
    }
    return "", false
})
Reduction
// Apply a function to each element (for side effects)
numbers := xiter.Range1(5)
xiter.ForEach(numbers, func(x int) {
    fmt.Println(x)
})

// Reduce a sequence to a single value
numbers := xiter.Range1(10)
sum := xiter.Fold(numbers, 0, func(acc, x int) int { return acc + x })
Searching and Checking
// Check if a sequence contains an element
numbers := xiter.Range1(10)
hasFive := xiter.Contains(numbers, 5)

// Check if any element satisfies a condition
hasEven := xiter.Any(numbers, func(x int) bool { return x%2 == 0 })

// Check if all elements satisfy a condition
allPositive := xiter.All(numbers, func(x int) bool { return x > 0 })

// Find the first element that satisfies a condition
firstEven, found := xiter.FirstFunc(numbers, func(x int) bool { return x%2 == 0 })

// Find the last element
last, found := xiter.Last(numbers)
Sequence Operations
// Concatenate two sequences
seq1 := xiter.Range1(3)
seq2 := xiter.Range2(5, 8)
combined := xiter.Chain(seq1, seq2)

// Take the first 5 elements
firstFive := xiter.Take(numbers, 5)

// Skip the first 3 elements
rest := xiter.Skip(numbers, 3)

// Take elements while condition is true
untilFive := xiter.TakeWhile(numbers, func(x int) bool { return x < 5 })

Key-Value Pair Operations

xiter provides equivalent operations for key-value pair sequences (iter.Seq2[K, V]):

// Create key-value pairs
pairs := xiter.FromFunc2(func() (string, int, bool) {
    // ...
})

// Transform pairs
enhanced := xiter.Map2(pairs, func(k string, v int) (string, int) {
    return "enhanced_" + k, v * 2
})

// Filter pairs
validPairs := xiter.Filter2(enhanced, func(k string, v int) bool {
    return v > 5
})

// Reduce pairs
sum := xiter.Fold2(validPairs, 0, func(acc int, k string, v int) int {
    return acc + v
})

Best Practices

  1. Chain operations for readability: Combine multiple operations in a single pipeline
  2. Consume sequences efficiently: Iterators can only be consumed once
  3. Use lazy evaluation: Take advantage of xiter's lazy evaluation for large datasets
  4. Avoid unnecessary materialization: Prefer to work with iterators directly rather than converting to slices
  5. Leverage type inference: Let Go's type inference work for you when possible

Performance Considerations

  • All xiter operations are designed to be lightweight and efficient
  • Lazy evaluation means only elements that are actually consumed are processed
  • Memory usage is minimized since sequences are not fully materialized unless explicitly requested
  • For maximum performance, avoid unnecessary conversions between sequences and concrete types

Examples

Calculating Factorial
func Factorial(n int) int {
    numbers := xiter.Range2(1, n+1)
    return xiter.Fold(numbers, 1, func(acc, x int) int { return acc * x })
}
Processing Data from a Database
func ProcessUsers(db *sql.DB) error {
    rows, err := db.Query("SELECT id, name, email FROM users")
    if err != nil {
        return err
    }
    defer rows.Close()

    // Create a sequence from database rows
    userSeq := xiter.FromFunc2(func() (int, string, bool) {
        if !rows.Next() {
            return 0, "", false
        }
        var id int
        var name string
        if err := rows.Scan(&id, &name, nil); err != nil {
            return 0, "", false
        }
        return id, name, true
    })

    // Filter active users (assuming some condition)
    activeUsers := xiter.Filter2(userSeq, func(id int, name string) bool {
        // Implement your active user logic
        return id%2 == 0 // Example condition
    })

    // Process each active user
    xiter.ForEach2(activeUsers, func(id int, name string) {
        fmt.Printf("Processing user: %s (ID: %d)\n", name, id)
    })

    return nil
}
Working with Large Datasets
func ProcessLargeFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)

    // Create a sequence from file lines
    lines := xiter.FromFunc(func() (string, bool) {
        if !scanner.Scan() {
            return "", false
        }
        return scanner.Text(), true
    })

    // Filter and process lines
    longLines := xiter.Filter(lines, func(line string) bool { return len(line) > 100 })
    count := xiter.Fold(longLines, 0, func(acc int, line string) int {
        return acc + 1
    })

    fmt.Printf("Found %d lines longer than 100 characters\n", count)
    return nil
}

Contributing

Contributions are welcome! Please feel free to submit issues, pull requests, or feature suggestions.

Development Setup
  1. Fork the repository
  2. Clone your fork
  3. Create a feature branch
  4. Make your changes
  5. Run tests: go test ./...
  6. Submit a pull request

License

xiter is licensed under the Apache 2.0 License. See the LICENSE file for details.

Acknowledgments

  • Inspired by functional programming languages like Haskell, Scala, and JavaScript
  • Built on Go's excellent new iterators feature
  • Thanks to the Go community for their feedback and contributions

Support

If you encounter any issues or have questions, please file an issue on the GitHub repository.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[E any](s iter.Seq[E], f func(E) bool) bool

All reports whether all elements in the sequence satisfy the predicate.

func All2

func All2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) bool

All2 reports whether all key/value pairs in the sequence satisfy the predicate.

func Any

func Any[E any](s iter.Seq[E], f func(E) bool) bool

Any reports whether any element in the sequence satisfies the predicate.

func Any2

func Any2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) bool

Any2 reports whether any key/value pair in the sequence satisfies the predicate.

func Cast

func Cast[E any](s iter.Seq[any]) iter.Seq2[E, bool]

Cast converts a sequence of any into a sequence of E values, returning the converted value and a success flag for each element.

func Chain

func Chain[E any](seq1, seq2 iter.Seq[E]) iter.Seq[E]

Chain concatenates two sequences into a single sequence.

func Chain2

func Chain2[K, V any](seq1, seq2 iter.Seq2[K, V]) iter.Seq2[K, V]

Chain2 concatenates two key/value sequences into a single sequence.

func Compare

func Compare[E cmp.Ordered](x, y iter.Seq[E]) int

Compare reports the comparison result between two comparable sequences. It returns:

  • 0 if the sequences are equal
  • -1 if the first sequence is "less" than the second
  • 1 if the first sequence is "greater" than the second

func Compare2

func Compare2[K, V cmp.Ordered](x, y iter.Seq2[K, V]) int

Compare2 reports the comparison result between two comparable key/value sequences. It returns:

  • 0 if the sequences are equal
  • -1 if the first sequence is "less" than the second
  • 1 if the first sequence is "greater" than the second

func CompareFunc

func CompareFunc[E any](x, y iter.Seq[E], f func(E, E) int) int

CompareFunc compares two sequences using the provided comparison function. It returns:

  • 0 if the sequences are equal
  • -1 if the first sequence is "less" than the second
  • 1 if the first sequence is "greater" than the second

func CompareFunc2

func CompareFunc2[K, V any](x, y iter.Seq2[K, V], f func(K, V, K, V) int) int

CompareFunc2 compares two key/value sequences using the provided comparison function. It returns:

  • 0 if the sequences are equal
  • -1 if the first sequence is "less" than the second
  • 1 if the first sequence is "greater" than the second

func Contains

func Contains[E comparable](s iter.Seq[E], v E) bool

Contains reports whether the sequence contains the specified comparable element.

func Contains2

func Contains2[K, V comparable](s iter.Seq2[K, V], k K, v V) bool

Contains2 reports whether the key/value sequence contains the specified key and value.

func ContainsFunc

func ContainsFunc[E any](s iter.Seq[E], f func(E) bool) bool

ContainsFunc reports whether the sequence contains an element that satisfies the predicate.

func ContainsFunc2

func ContainsFunc2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) bool

func Empty

func Empty[E any]() iter.Seq[E]

Empty generates an empty sequence.

func Empty2

func Empty2[K, V any]() iter.Seq2[K, V]

Empty2 generates an empty key/value sequence.

func Enumerate

func Enumerate[E any](s iter.Seq[E]) iter.Seq2[int, E]

Enumerate returns a sequence of (index, element) tuples, adding an index for each element in the input sequence.

func Equal

func Equal[E comparable](x, y iter.Seq[E]) bool

Equal reports whether two comparable sequences are equal (same length and values).

func Equal2

func Equal2[K, V comparable](x, y iter.Seq2[K, V]) bool

Equal2 reports whether two key/value sequences are equal (comparable keys and values must match).

func EqualFunc

func EqualFunc[E any](x, y iter.Seq[E], f func(E, E) bool) bool

EqualFunc compares two sequences using the provided comparison function.

func EqualFunc2

func EqualFunc2[K, V any](x, y iter.Seq2[K, V], f func(K, V, K, V) bool) bool

EqualFunc2 compares two key/value sequences using the provided comparison function.

func Filter

func Filter[E any](s iter.Seq[E], f func(E) bool) iter.Seq[E]

Filter returns a new sequence containing only elements that satisfy the predicate.

func Filter2

func Filter2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) iter.Seq2[K, V]

Filter2 returns a new key/value sequence containing only pairs that satisfy the predicate.

func FilterMap

func FilterMap[E1, E2 any](s iter.Seq[E1], f func(E1) (E2, bool)) iter.Seq[E2]

FilterMap applies the provided function to each element, which returns a value and a boolean. Only values with a true boolean are kept.

func FilterMap2

func FilterMap2[K1, V1, K2, V2 any](s iter.Seq2[K1, V1], f func(K1, V1) (K2, V2, bool)) iter.Seq2[K2, V2]

FilterMap2 applies the provided function to each key/value pair, which returns a key, value, and boolean. Only pairs with a true boolean are kept.

func First

func First[E any](s iter.Seq[E]) (E, bool)

First returns the first element of the sequence. If the sequence is empty, it returns the zero value and false.

func First2

func First2[K, V any](s iter.Seq2[K, V]) (K, V, bool)

First2 returns the first key/value pair of the sequence. If the sequence is empty, it returns the zero values and false.

func FirstFunc

func FirstFunc[E any](s iter.Seq[E], f func(E) bool) (E, bool)

FirstFunc returns the first element that satisfies the predicate. If no such element exists, it returns the zero value and false.

func FirstFunc2

func FirstFunc2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) (K, V, bool)

FirstFunc2 returns the first key/value pair that satisfies the predicate. If no such pair exists, it returns the zero values and false.

func FlatMap

func FlatMap[E1, E2 any](s iter.Seq[E1], f func(E1) iter.Seq[E2]) iter.Seq[E2]

FlatMap applies the provided function to each element, which returns a sequence, and then flattens the result into a single sequence.

func Flatten

func Flatten[E any](s iter.Seq[iter.Seq[E]]) iter.Seq[E]

Flatten returns a flattened sequence from a sequence of sequences.

func Fold

func Fold[E any, A any](s iter.Seq[E], init A, f func(A, E) A) A

Fold reduces a sequence into a single value by applying the given function to each element.

func Fold2

func Fold2[K, V, A any](s iter.Seq2[K, V], init A, f func(A, K, V) A) A

Fold2 reduces a key/value sequence into a single value by applying the given function to each pair.

func ForEach

func ForEach[E any](s iter.Seq[E], f func(E))

ForEach applies the provided function to each element (no return value), typically for side effects such as printing or mutating external state.

func ForEach2

func ForEach2[K, V any](s iter.Seq2[K, V], f func(K, V))

ForEach2 applies the provided function to each key/value pair (no return value), typically for side effects.

func FromFunc

func FromFunc[E any](f func() (E, bool)) iter.Seq[E]

FromFunc generates a sequence from a function that returns (element, continue). The sequence ends when continue is false.

func FromFunc2

func FromFunc2[K, V any](f func() (K, V, bool)) iter.Seq2[K, V]

FromFunc2 generates a key/value sequence from a function that returns (key, value, continue). The sequence ends when continue is false.

func IsSorted

func IsSorted[E cmp.Ordered](s iter.Seq[E]) bool

IsSorted checks if the elements of the sequence are sorted in ascending order.

func IsSortedFunc

func IsSortedFunc[E any](s iter.Seq[E], f func(E, E) int) bool

IsSortedFunc reports whether the sequence is sorted according to a consistent order (ascending or descending) using the provided comparison function.

func Join

func Join[E, K, V any](s iter.Seq2[K, V], f func(K, V) E) iter.Seq[E]

Join turns a key/value sequence into an element sequence using the provided mapping function.

func Last

func Last[E any](s iter.Seq[E]) (E, bool)

Last returns the last element of the sequence. If the sequence is empty, it returns the zero value and false.

func Last2

func Last2[K, V any](s iter.Seq2[K, V]) (K, V, bool)

Last2 returns the last key/value pair of the sequence. If the sequence is empty, it returns the zero values and false.

func LastFunc

func LastFunc[E any](s iter.Seq[E], f func(E) bool) (E, bool)

LastFunc returns the last element that satisfies the predicate. If no such element exists, it returns the zero value and false.

func LastFunc2

func LastFunc2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) (K, V, bool)

LastFunc2 returns the last key/value pair that satisfies the predicate. If no such pair exists, it returns the zero values and false.

func Map

func Map[E1, E2 any](s iter.Seq[E1], f func(E1) E2) iter.Seq[E2]

Map applies the provided function to each element and returns a new sequence with the results.

func Map2

func Map2[K1, V1, K2, V2 any](s iter.Seq2[K1, V1], f func(K1, V1) (K2, V2)) iter.Seq2[K2, V2]

Map2 applies the provided function to each element of a key/value sequence and returns a new key/value sequence with the results.

func MapWhile

func MapWhile[E1, E2 any](s iter.Seq[E1], f func(E1) (E2, bool)) iter.Seq[E2]

MapWhile applies the provided function to each element and returns a new sequence with the results, until the function returns false.

func MapWhile2

func MapWhile2[K1, V1, K2, V2 any](s iter.Seq2[K1, V1], f func(K1, V1) (K2, V2, bool)) iter.Seq2[K2, V2]

MapWhile2 applies the provided function to each element of a key/value sequence and returns a new key/value sequence with the results, until the function returns false.

func Max

func Max[E cmp.Ordered](s iter.Seq[E]) (E, bool)

Max returns the maximum element in the sequence using cmp.Compare. If the sequence is empty, it returns the zero value and false.

func MaxFunc

func MaxFunc[E any](s iter.Seq[E], cmp func(E, E) int) (E, bool)

MaxFunc returns the maximum element in the sequence using a custom compare function. If the sequence is empty, it returns the zero value and false.

func Min

func Min[E cmp.Ordered](s iter.Seq[E]) (E, bool)

Min returns the minimum element in the sequence using cmp.Compare. If the sequence is empty, it returns the zero value and false.

func MinFunc

func MinFunc[E any](s iter.Seq[E], cmp func(E, E) int) (E, bool)

MinFunc returns the minimum element in the sequence using a custom compare function. If the sequence is empty, it returns the zero value and false.

func Once

func Once[E any](e E) iter.Seq[E]

Once generates a sequence containing a single element.

func Once2

func Once2[K, V any](k K, v V) iter.Seq2[K, V]

Once2 generates a sequence containing a single key/value pair.

func Position

func Position[E any](s iter.Seq[E], f func(E) bool) (int, bool)

Position returns the index of the first element that satisfies the predicate.

func Position2

func Position2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) (int, bool)

Position2 returns the index of the first key/value pair that satisfies the predicate.

func Range1

func Range1[N integral](end N) iter.Seq[N]

Range1 generates an integer sequence from 0 to end-1 (end not included).

func Range2

func Range2[N integral](start, end N) iter.Seq[N]

Range2 generates an integer sequence from start to end-1 (end not included).

func Range3

func Range3[N integral](start, end, step N) iter.Seq[N]

Range3 generates an integer sequence from start to end-1 with a step size (end not included).

func Repeat

func Repeat[E any](e E) iter.Seq[E]

Repeat generates an infinite sequence repeating a single element.

func Repeat2

func Repeat2[K, V any](k K, v V) iter.Seq2[K, V]

Repeat2 generates an infinite sequence repeating a single key/value pair.

func Size

func Size[E any](s iter.Seq[E]) int

Size returns the number of elements in the sequence.

func Size2

func Size2[K, V any](s iter.Seq2[K, V]) int

Size2 returns the number of key/value pairs in the sequence.

func SizeFunc

func SizeFunc[E any](s iter.Seq[E], f func(E) bool) int

SizeFunc returns the number of elements that satisfy the predicate.

func SizeFunc2

func SizeFunc2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) int

SizeFunc2 returns the number of key/value pairs that satisfy the predicate.

func SizeValue

func SizeValue[E comparable](s iter.Seq[E], v E) int

SizeValue returns the number of elements equal to the specified value.

func SizeValue2

func SizeValue2[K, V comparable](s iter.Seq2[K, V], k K, v V) int

SizeValue2 returns the number of key/value pairs whose key and value equal the specified values.

func Skip

func Skip[E any](s iter.Seq[E], n int) iter.Seq[E]

Skip returns a sequence that skips the first n elements.

func Skip2

func Skip2[K, V any](s iter.Seq2[K, V], n int) iter.Seq2[K, V]

Skip2 returns a key/value sequence that skips the first n elements.

func SkipWhile

func SkipWhile[E any](s iter.Seq[E], f func(E) bool) iter.Seq[E]

SkipWhile returns a sequence that skips elements while the predicate holds.

func SkipWhile2

func SkipWhile2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) iter.Seq2[K, V]

SkipWhile2 returns a key/value sequence that skips elements while the predicate holds.

func Split

func Split[K, V, E any](s iter.Seq[E], f func(E) (K, V)) iter.Seq2[K, V]

Split turns an element sequence into a key/value sequence using the provided split function.

func Take

func Take[E any](s iter.Seq[E], n int) iter.Seq[E]

Take returns the first n elements of the sequence.

func Take2

func Take2[K, V any](s iter.Seq2[K, V], n int) iter.Seq2[K, V]

Take2 returns the first n elements of a key/value sequence.

func TakeWhile

func TakeWhile[E any](s iter.Seq[E], f func(E) bool) iter.Seq[E]

TakeWhile returns a sequence that yields elements until the predicate fails.

func TakeWhile2

func TakeWhile2[K, V any](s iter.Seq2[K, V], f func(K, V) bool) iter.Seq2[K, V]

TakeWhile2 returns a key/value sequence that yields elements until the predicate fails.

Types

This section is empty.

Jump to

Keyboard shortcuts

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