seqerr

package
v1.8.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2025 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package seqerr provides specialized utilities for handling errors when working with iter.Seq in Go applications.

The goal of this package is to simplify error handling in sequence processing pipelines by offering functions that work with iter.Seq2 where the second value represents an error. These utilities automatically break iteration when an error is encountered and propagate it through the processing chain, allowing errors to be collected and handled at the end of the pipeline.

The package includes error-aware versions of common sequence operations such as mapping, filtering, and reducing, enabling developers to write clean and robust sequence processing code without explicitly handling errors at each step. This approach reduces boilerplate code and improves readability by separating the error handling logic from the business logic.

By integrating seamlessly with the iter.Seq ecosystem, this package provides a consistent way to manage errors across sequence operations, making it easier to build reliable data processing pipelines.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Append added in v1.1.0

func Append[E any](seq iter.Seq2[E, error], elem E) iter.Seq2[E, error]

Append appends element to the end of a sequence.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := seq.Range(1, 4)

	// Append number 4 to the sequence
	appended := seqerr.Append(seqerr.FromSeq(sequence), 4)

	// Collect results
	for n, err := range appended {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
2
3
4

func Collect

func Collect[E any](seq iter.Seq2[E, error]) ([]E, error)

Collect collects the elements of the given sequence into a slice.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Collect elements into a new slice
	result, err := seqerr.Collect(sequence)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(result)

}
Output:

[1 2 3]
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with an error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Collect elements into a new slice
	result, err := seqerr.Collect(sequence)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(result)

}
Output:

Error: source error
[1]

func Concat added in v1.1.0

func Concat[E any](sequences ...iter.Seq2[E, error]) iter.Seq2[E, error]

Concat concatenates multiple sequences into a single sequence.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create first sequence with numbers 1-2
	first := seqerr.FromSeq(seq.Range(1, 3))

	// Create second sequence with numbers 3-4
	second := seqerr.FromSeq(seq.Range(3, 5))

	// Concatenate the two sequences
	combined := seqerr.Concat(first, second)

	// Collect results
	for n, err := range combined {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
2
3
4
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create first sequence with an error
	first := iter.Seq2[int, error](func(yield func(int, error) bool) {
		if !yield(1, nil) {
			return
		}
		if !yield(2, errors.New("first sequence error")) {
			return
		}
		// This won't be processed due to the error
		if !yield(3, nil) {
			return
		}
	})

	// Create second sequence
	second := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 4; i <= 5; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Concatenate the two sequences
	combined := seqerr.Concat(first, second)

	// Collect results
	for n, err := range combined {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
Error: first sequence error

func Count

func Count[E any](seq iter.Seq2[E, error]) (int, error)

Count returns the number of elements in the sequence.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Count elements in the sequence
	count, err := seqerr.Count(sequence)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(count)

}
Output:

3
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with an error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Count elements in the sequence
	count, err := seqerr.Count(sequence)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(count)

}
Output:

Error: source error
0

func Each added in v0.10.0

func Each[E any, C Consumer[E]](seq iter.Seq2[E, error], consumer C) iter.Seq2[E, error]

Each returns a sequence that applies the given consumer to each element of the input sequence and pass it further. Each is an alias for Tap. Comparing to ForEach, this is a lazy function and doesn't consume the input sequence.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Use Each (alias for Tap) to print each element while passing it through
	each := seqerr.Each(sequence, func(n int) {
		fmt.Printf("Element: %d\n", n)
	})

	// Collect the elements after processing
	result, err := seqerr.Collect(each)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Result:", result)

}
Output:

Element: 1
Element: 2
Element: 3
Result: [1 2 3]

func Filter

func Filter[E any, P Predicate[E]](seq iter.Seq2[E, error], predicate P) iter.Seq2[E, error]

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

Example (PredicateWithError)
package main

import (
	"fmt"
	"iter"
	"strconv"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := iter.Seq2[string, error](func(yield func(string, error) bool) {
		for i := range 5 {
			if !yield(fmt.Sprintf("%d", i), nil) {
				break
			}
		}
	})

	// Filter strings that are even numbers when converted to int
	filtered := seqerr.Filter(sequence, func(s string) (bool, error) {
		i, err := strconv.Atoi(s)
		if err != nil {
			return false, err
		}
		return i%2 == 0, nil
	})

	// Print results
	for s, err := range filtered {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(s)
	}

}
Output:

0
2
4
Example (PredicateWithoutError)
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := range 5 {
			yield(i, nil)
		}
	})

	// Filter even numbers
	evenNumbers := seqerr.Filter(sequence, func(n int) bool {
		return n%2 == 0
	})

	// Print results
	for n, err := range evenNumbers {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
2
4
Example (SourceError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence that produces an error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := range 5 {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Filter even numbers
	filtered := seqerr.Filter(sequence, func(n int) bool {
		return n%2 == 0
	})

	// Collect results
	for n, err := range filtered {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
Error: source error
Example (Validator)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := range 5 {
			if !yield(i+1, nil) {
				break
			}
		}
	})

	// Filter using a validator (non-zero values)
	nonZero := seqerr.Filter(sequence, func(n int) error {
		if n%2 == 0 {
			return errors.New("even value not allowed")
		}
		return nil
	})

	// Collect results
	for n, err := range nonZero {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
Error: even value not allowed

func FlatMap

func FlatMap[E any, R any](seq iter.Seq2[E, error], mapper MapperWithoutError[E, iter.Seq[R]]) iter.Seq2[R, error]

FlatMap applies a mapper function to each element of the sequence and flattens the result.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// FlatMap to create duplicates of each number
	duplicated := seqerr.FlatMap(sequence, func(n int) iter.Seq[int] {
		return seq.Repeat(n, 2)
	})

	// Collect results
	for n, err := range duplicated {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
1
2
2
3
3

func FlatMapOrErr

func FlatMapOrErr[E any, R any](seq iter.Seq2[E, error], mapper MapperWithError[E, iter.Seq[R]]) iter.Seq2[R, error]

FlatMapOrErr applies a mapper function that can return error to each element of the sequence and flattens the result.

Example
package main

import (
	"fmt"
	"iter"
	"strconv"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of strings
	sequence := iter.Seq2[string, error](func(yield func(string, error) bool) {
		for i := 1; i <= 3; i++ {
			var value string
			if i == 2 {
				value = "two"
			} else {
				value = strconv.Itoa(i)
			}
			if !yield(value, nil) {
				break
			}
		}
	})

	// Duplicate integers or return an error if cannot be parsed
	numbers := seqerr.FlatMapOrErr(sequence, func(s string) (iter.Seq[int], error) {
		i, err := strconv.Atoi(s)
		if err != nil {
			return nil, err
		}
		return seq.Repeat(i, 2), nil
	})

	// Collect results
	for n, err := range numbers {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
1
Error: strconv.Atoi: parsing "two": invalid syntax

func Flatten

func Flatten[Seq iter.Seq2[iter.Seq[E], error], E any](seq Seq) iter.Seq2[E, error]

Flatten flattens a sequence of sequences.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of sequences
	sequence := seq.RangeTo(3)

	seqOfSeq := seqerr.MapSeq(sequence, func(n int) (iter.Seq[int], error) {
		return seq.Repeat(n, 2), nil
	})

	// Flatten the sequence of sequences
	flattened := seqerr.Flatten(seqOfSeq)

	// Collect results
	for n, err := range flattened {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
0
1
1
2
2

func FlattenSlices

func FlattenSlices[Seq iter.Seq2[[]E, error], E any](seq Seq) iter.Seq2[E, error]

FlattenSlices flattens a sequence of slices.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of slices
	sequence := iter.Seq2[[]int, error](func(yield func([]int, error) bool) {
		slices := [][]int{{1, 2}, {3, 4, 5}, {6}}
		for _, slice := range slices {
			if !yield(slice, nil) {
				break
			}
		}
	})

	// Flatten the sequence of slices
	flattened := seqerr.FlattenSlices(sequence)

	// Collect results
	for n, err := range flattened {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
2
3
4
5
6
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of slices with an error
	sequence := iter.Seq2[[]int, error](func(yield func([]int, error) bool) {
		if !yield([]int{1, 2}, nil) {
			return
		}
		if !yield(nil, errors.New("slice error")) {
			return
		}
		// This won't be processed due to the error
		if !yield([]int{3, 4}, nil) {
			return
		}
	})

	// Flatten the sequence of slices
	flattened := seqerr.FlattenSlices(sequence)

	// Collect results
	for n, err := range flattened {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
2
Error: slice error

func Fold

func Fold[E any](seq iter.Seq2[E, error], accumulator func(agg E, item E) E) (optional.Value[E], error)

Fold applies a function against an accumulator and each element in the sequence (from left to right) to reduce it to a single value.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 5; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Calculate the product of all numbers
	result, err := seqerr.Fold(sequence, func(acc int, item int) int {
		return acc * item
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	if result.IsPresent() {
		fmt.Println("Product:", result.MustGet())
	} else {
		fmt.Println("Empty sequence")
	}

}
Output:

Product: 120
Example (EmptySequence)
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create an empty sequence
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		// Do nothing
	})

	// Try to fold the empty sequence
	result, err := seqerr.Fold(sequence, func(acc int, item int) int {
		return acc + item
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	if result.IsPresent() {
		fmt.Println("Sum:", result.MustGet())
	} else {
		fmt.Println("Empty sequence")
	}

}
Output:

Empty sequence

func FoldRight

func FoldRight[E any](seq iter.Seq2[E, error], accumulator func(agg E, item E) E) (optional.Value[E], error)

FoldRight applies a function against an accumulator and each element in the sequence (from right to left) to reduce it to a single value.

Example
package main

import (
	"fmt"
	"iter"
	"strings"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with strings
	sequence := iter.Seq2[string, error](func(yield func(string, error) bool) {
		words := []string{"hello", "world"}
		for _, word := range words {
			if !yield(word, nil) {
				break
			}
		}
	})

	// Concatenate strings right-to-left
	result, err := seqerr.FoldRight(sequence, func(acc string, item string) string {
		return strings.ToUpper(acc) + "-" + item
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	if result.IsPresent() {
		fmt.Println(result.MustGet())
	} else {
		fmt.Println("Empty sequence")
	}

}
Output:

WORLD-hello

func ForEach added in v0.10.0

func ForEach[E any, C Consumer[E]](seq iter.Seq2[E, error], consumer C) error

ForEach applies consumer to each element of the input sequence. Comparing to Each, this is not a lazy function and consumes the input sequence.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Use ForEach to process all elements
	sum := 0
	err := seqerr.ForEach(sequence, func(n int) {
		fmt.Printf("Adding: %d\n", n)
		sum += n
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Sum:", sum)

}
Output:

Adding: 1
Adding: 2
Adding: 3
Sum: 6
Example (WithConsumerError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Use ForEach with a consumer that returns an error
	sum := 0
	err := seqerr.ForEach(sequence, func(n int) error {
		if n == 2 {
			return errors.New("consumer error")
		}
		fmt.Printf("Adding: %d\n", n)
		sum += n
		return nil
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Sum:", sum)

}
Output:

Adding: 1
Error: consumer error
Sum: 1
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Use ForEach to process elements
	sum := 0
	err := seqerr.ForEach(sequence, func(n int) {
		fmt.Printf("Adding: %d\n", n)
		sum += n
	})

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Sum:", sum)

}
Output:

Adding: 1
Error: source error
Sum: 1

func FromSeq added in v0.12.0

func FromSeq[E any](sequence iter.Seq[E]) iter.Seq2[E, error]

FromSeq converts a sequence of elements into a sequence of elements and nil errors.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence without errors first
	originalSeq := func(yield func(int) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i) {
				break
			}
		}
	}

	// Convert to sequence with error handling
	sequence := seqerr.FromSeq(originalSeq)

	for item, err := range sequence {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(item)
	}

}
Output:

1
2
3

func FromSlice added in v0.12.0

func FromSlice[E any](slice []E) iter.Seq2[E, error]

FromSlice converts a slice of elements into a sequence of elements and nil errors.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	slice := []string{"a", "b", "c"}
	sequence := seqerr.FromSlice(slice)

	for item, err := range sequence {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(item)
	}

}
Output:

a
b
c

func Map

func Map[E any, R any](seq iter.Seq2[E, error], mapper MapperWithoutError[E, R]) iter.Seq2[R, error]

Map applies a mapper function to each element of the sequence.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			yield(i, nil)
		}
	})

	// Map numbers to their squares
	squared := seqerr.Map(sequence, func(n int) int {
		return n * n
	})

	// Collect results
	for n, err := range squared {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
4
9
Example (SourceError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Map numbers to their squares
	squared := seqerr.Map(sequence, func(n int) int {
		return n * n
	})

	// Collect results
	for n, err := range squared {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
Error: source error

func MapOrErr

func MapOrErr[E any, R any](seq iter.Seq2[E, error], mapper MapperWithError[E, R]) iter.Seq2[R, error]

MapOrErr applies a mapper function that can return error to each element of the sequence.

Example
package main

import (
	"fmt"
	"iter"
	"strconv"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of strings
	sequence := iter.Seq2[string, error](func(yield func(string, error) bool) {
		for i := 1; i <= 3; i++ {
			var value string
			if i == 2 {
				value = "two"
			} else {
				value = strconv.Itoa(i)
			}
			if !yield(value, nil) {
				break
			}
		}
	})

	// Map strings to integers
	numbers := seqerr.MapOrErr(sequence, func(s string) (int, error) {
		return strconv.Atoi(s)
	})

	// Collect results
	for n, err := range numbers {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
Error: strconv.Atoi: parsing "two": invalid syntax

func MapSeq

func MapSeq[E any, R any](seq iter.Seq[E], mapper MapperWithError[E, R]) iter.Seq2[R, error]

MapSeq applies a mapper function to each element of the sequence. The mapper function can return an error.

func Of added in v0.12.0

func Of[E any](elements ...E) iter.Seq2[E, error]

Of creates a new sequence of elements and nil errors, from the provided elements.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := seqerr.Of(1, 2, 3)

	for item, err := range sequence {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(item)
	}

}
Output:

1
2
3

func Prepend added in v1.1.0

func Prepend[E any](seq iter.Seq2[E, error], elem E) iter.Seq2[E, error]

Prepend prepends element to the beginning of a sequence.

Example
package main

import (
	"fmt"

	"github.com/go-softwarelab/common/pkg/seq"
	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 2-4
	sequence := seq.Range(2, 5)

	// Prepend number 1 to the sequence
	prepended := seqerr.Prepend(seqerr.FromSeq(sequence), 1)

	// Collect results
	for n, err := range prepended {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

1
2
3
4

func Produce

func Produce[E, A any](next func(A) ([]E, A, error)) iter.Seq2[[]E, error]

Produce returns a new sequence that is filled by the results of calling the next function.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := seqerr.Produce(func(i int) ([]string, int, error) {
		if i == 2 {
			return []string{}, i + 1, nil
		}

		num := strconv.Itoa(i)
		result := []string{"a" + num, "b" + num, "c" + num}
		return result, i + 1, nil
	})

	for item, err := range sequence {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(item)
	}

}
Output:

[a0 b0 c0]
[a1 b1 c1]

func ProduceWithArg

func ProduceWithArg[E, A any](next func(A) ([]E, A, error), arg A) iter.Seq2[[]E, error]

ProduceWithArg returns a new sequence that is filled by the results of calling the next function with the provided argument.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	sequence := seqerr.ProduceWithArg(func(i int) ([]string, int, error) {
		if i == 2 {
			return []string{}, i + 1, nil
		}

		num := strconv.Itoa(i)
		result := []string{"a" + num, "b" + num, "c" + num}
		return result, i + 1, nil
	}, 1)

	for item, err := range sequence {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(item)
	}

}
Output:

[a1 b1 c1]

func Reduce

func Reduce[E any, R any](seq iter.Seq2[E, error], accumulator func(agg R, item E) R, initial R) (R, error)

Reduce applies a function against an accumulator and each element in the sequence (from left to right) to reduce it to a single value.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-5
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 5; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Sum all numbers
	sum, err := seqerr.Reduce(sequence, func(acc int, item int) int {
		return acc + item
	}, 0)

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Println("Sum:", sum)

}
Output:

Sum: 15
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with an error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 5; i++ {
			var err error
			if i == 3 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Sum all numbers
	sum, err := seqerr.Reduce(sequence, func(acc int, item int) int {
		return acc + item
	}, 0)

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Println("Sum:", sum)

}
Output:

Error: source error
Sum: 0

func ReduceRight

func ReduceRight[E any, R any](seq iter.Seq2[E, error], accumulator func(agg R, item E) R, initial R) (R, error)

ReduceRight applies a function against an accumulator and each element in the sequence (from right to left) to reduce it to a single value.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with words
	sequence := iter.Seq2[string, error](func(yield func(string, error) bool) {
		words := []string{"hello", "beautiful", "world"}
		for _, word := range words {
			if !yield(word, nil) {
				break
			}
		}
	})

	// Join words right-to-left
	joined, err := seqerr.ReduceRight(sequence, func(acc string, item string) string {
		if acc == "" {
			return item
		}
		return item + " " + acc
	}, "")

	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Println(joined)

}
Output:

hello beautiful world

func Take added in v0.9.0

func Take[E any](seq iter.Seq2[E, error], n int) iter.Seq2[E, error]

Take returns a new sequence that contains only the first n elements of the given sequence.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := range 10 {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Take only the first 3 elements
	taken := seqerr.Take(sequence, 3)

	// Print results
	for n, err := range taken {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
1
2

func TakeUntil added in v0.9.0

func TakeUntil[E any, P Predicate[E]](seq iter.Seq2[E, error], predicate P) iter.Seq2[E, error]

TakeUntil returns a new sequence that takes elements from the given sequence until the predicate is satisfied.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 0; i < 10; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Take elements until we find one that's equal to 5
	taken := seqerr.TakeUntil(sequence, func(n int) bool {
		return n == 5
	})

	// Print results
	for n, err := range taken {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
1
2
3
4

func TakeUntilTrue added in v0.9.0

func TakeUntilTrue[E any](seq iter.Seq2[E, error], stopCondition func() bool) iter.Seq2[E, error]

TakeUntilTrue returns a new sequence that takes elements from the given sequence until the stop condition is satisfied. If condition is met before the first element, the sequence will not yield any elements.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 0; i < 10; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Create a condition that true
	condition := func() bool {
		return true
	}

	// Take elements until the condition becomes true
	taken := seqerr.TakeUntilTrue(sequence, condition)

	// Print results
	for n, err := range taken {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}

func TakeWhile added in v0.9.0

func TakeWhile[E any, P Predicate[E]](seq iter.Seq2[E, error], predicate P) iter.Seq2[E, error]

TakeWhile returns a new sequence that takes elements from the given sequence while the predicate is satisfied.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 0; i < 10; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Take elements while they are less than 5
	taken := seqerr.TakeWhile(sequence, func(n int) bool {
		return n < 5
	})

	// Print results
	for n, err := range taken {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}
Output:

0
1
2
3
4

func TakeWhileTrue added in v0.9.0

func TakeWhileTrue[E any](seq iter.Seq2[E, error], continueCondition func() bool) iter.Seq2[E, error]

TakeWhileTrue returns a new sequence that takes elements from the given sequence while the stop condition is satisfied. If condition is met before the first element, the sequence will not yield any elements.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence of numbers
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 0; i < 10; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Create a condition that false
	condition := func() bool {
		return false
	}

	// Take elements while the condition remains true
	taken := seqerr.TakeWhileTrue(sequence, condition)

	// Print results
	for n, err := range taken {
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			break
		}
		fmt.Println(n)
	}

}

func Tap added in v0.10.0

func Tap[E any, C Consumer[E]](seq iter.Seq2[E, error], consumer C) iter.Seq2[E, error]

Tap returns a sequence that applies the given consumer to each element of the input sequence and pass it further. In case if consumer returns an error, the sequence stops and pass only the error from consumer further.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Use Tap to print each element while passing it through
	tapped := seqerr.Tap(sequence, func(n int) {
		fmt.Printf("Processing: %d\n", n)
	})

	// Collect the elements after tapping
	result, err := seqerr.Collect(tapped)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Result:", result)

}
Output:

Processing: 1
Processing: 2
Processing: 3
Result: [1 2 3]
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Use Tap with a consumer that returns an error
	tapped := seqerr.Tap(sequence, func(n int) error {
		if n == 2 {
			return errors.New("consumer error")
		}
		fmt.Printf("Processing: %d\n", n)
		return nil
	})

	// Collect the elements after tapping
	result, err := seqerr.Collect(tapped)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println("Result:", result)

}
Output:

Processing: 1
Error: consumer error
Result: [1]

func ToSlice

func ToSlice[Slice ~[]E, E any](seq iter.Seq2[E, error], slice Slice) (Slice, error)

ToSlice collects the elements of the given sequence into a slice.

Example
package main

import (
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with numbers 1-3
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			if !yield(i, nil) {
				break
			}
		}
	})

	// Collect elements into a slice
	slice, err := seqerr.ToSlice(sequence, make([]int, 0))
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(slice)

}
Output:

[1 2 3]
Example (WithError)
package main

import (
	"errors"
	"fmt"
	"iter"

	"github.com/go-softwarelab/common/pkg/seqerr"
)

func main() {
	// Create a sequence with an error
	sequence := iter.Seq2[int, error](func(yield func(int, error) bool) {
		for i := 1; i <= 3; i++ {
			var err error
			if i == 2 {
				err = errors.New("source error")
			}
			if !yield(i, err) {
				break
			}
		}
	})

	// Collect elements into a slice
	slice, err := seqerr.ToSlice(sequence, make([]int, 0))
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Println(slice)

}
Output:

Error: source error
[1]

Types

type Consumer added in v0.10.0

type Consumer[E any] interface {
	func(E) error | func(E)
}

Consumer is a function that is consuming the sequence.

type ConsumerWithError added in v0.10.0

type ConsumerWithError[E any] = func(E) error

ConsumerWithError is a function that takes an element and returns an error.

type ConsumerWithoutError added in v0.10.0

type ConsumerWithoutError[E any] = func(E)

ConsumerWithoutError is a function that takes an element and returns nothing.

type Mapper

type Mapper[E any, R any] interface {
	func(E) R | func(E) (R, error)
}

Mapper is a function that takes an element and returns a result. It can return an error.

type MapperWithError

type MapperWithError[E any, R any] = func(E) (R, error)

MapperWithError is a function that takes an element and returns a result and an error.

type MapperWithoutError

type MapperWithoutError[E any, R any] = func(E) R

MapperWithoutError is a function that takes an element and returns a result.

type Predicate

type Predicate[E any] interface {
	func(E) (bool, error) | func(E) bool | func(E) error
}

Predicate is a function that takes an element and returns a boolean. It can return an error.

type PredicateWithError

type PredicateWithError[E any] = func(E) (bool, error)

PredicateWithError is a function that takes an element and returns a boolean, it can fail with error.

type PredicateWithoutError

type PredicateWithoutError[E any] = func(E) bool

PredicateWithoutError is a function that takes an element and returns a boolean.

type Validator

type Validator[E any] = func(E) error

Validator is a function that takes an element and returns an error.

Jump to

Keyboard shortcuts

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