interx

package
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package interx provides lazy, context-aware sequence transformations for Go 1.23 iter.Seq values.

The interx package is useful when you want to build allocation-light data pipelines over slices, files, database rows, or generated streams without materializing every intermediate result. Each helper returns a new lazy sequence or consumes one directly, so work only happens when the caller ranges over the final sequence.

Example:

ctx := context.Background()
numbers := slices.Values([]int{1, 2, 3, 4, 5})

for v := range interx.Filter(ctx, numbers, func(n int) bool {
	return n%2 == 0
}) {
	fmt.Println(v)
}

Any important notes about behaviour such as laziness, context cancellation, memory usage. Most functions are lazy and stop as soon as the context is cancelled or the consumer breaks early. Reverse buffers the full sequence in memory before yielding results, while helpers like Filter, Map, and Take stream values one at a time.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Chunk

func Chunk[T any](ctx context.Context, seq iter.Seq[T], n int) iter.Seq[[]T]

Chunk splits a sequence into slices of size n.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 4, 5})

	for batch := range vinterx.Chunk(context.Background(), numbers, 2) {
		fmt.Println(batch)
	}
}
Output:
[1 2]
[3 4]
[5]

func Contains

func Contains[T comparable](ctx context.Context, seq iter.Seq[T], target T) bool

Contains returns true if the sequence contains the target value.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 4, 5})

	fmt.Println(vinterx.Contains(context.Background(), numbers, 3))
}
Output:
true

func Distinct

func Distinct[T comparable](ctx context.Context, seq iter.Seq[T]) iter.Seq[T]

Distinct filters out duplicate values keeping only the first occurrence.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 1, 3, 2, 4})

	for v := range vinterx.Distinct(context.Background(), numbers) {
		fmt.Println(v)
	}
}
Output:
1
2
3
4

func Drain

func Drain[T any](ctx context.Context, seq iter.Seq[T], fn func(T) error) error

Drain consumes a sequence and calls fn for each item. Stops immediately if ctx is cancelled or fn returns an error. Use Drain when your terminal operation can fail — writing to CSV, DB, files. Use ForEach when your terminal operation cannot fail — logging, printing.

example:

err := interx.Drain(ctx, users, func(u User) error {
    return csvWriter.Write([]string{u.Name, u.Email})
})
Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3})

	_ = vinterx.Drain(context.Background(), numbers, func(n int) error {
		fmt.Println(n)
		return nil
	})
}
Output:
1
2
3

func Filter

func Filter[T any](ctx context.Context, seq iter.Seq[T], fn func(T) bool) iter.Seq[T]

Filter returns a new sequence containing only elements where fn returns true.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 4, 5})

	for v := range vinterx.Filter(context.Background(), numbers, func(n int) bool {
		return n > 2
	}) {
		fmt.Println(v)
	}
}
Output:
3
4
5

func FlatMap

func FlatMap[T, U any](ctx context.Context, seq iter.Seq[T], fn func(T) iter.Seq[U]) iter.Seq[U]

FlatMap transforms each element into a sequence, then flattens all sequences.

Example
package main

import (
	"context"
	"fmt"
	"iter"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3})

	for v := range vinterx.FlatMap(context.Background(), numbers, func(n int) iter.Seq[int] {
		return slices.Values([]int{n, n * 10})
	}) {
		fmt.Println(v)
	}
}
Output:
1
10
2
20
3
30

func Flatten

func Flatten[T any](ctx context.Context, seq iter.Seq[[]T]) iter.Seq[T]

Flatten converts a sequence of slices into a flat sequence of elements.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	groups := slices.Values([][]int{{1, 2}, {3}, {4, 5}})

	for v := range vinterx.Flatten(context.Background(), groups) {
		fmt.Println(v)
	}
}
Output:
1
2
3
4
5

func ForEach

func ForEach[T any](ctx context.Context, seq iter.Seq[T], fn func(T))

ForEach calls fn for every element in the sequence.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3})

	vinterx.ForEach(context.Background(), numbers, func(v int) {
		fmt.Println(v * 2)
	})
}
Output:
2
4
6

func Map

func Map[T, U any](ctx context.Context, seq iter.Seq[T], fn func(T) U) iter.Seq[U]

Map transforms each element using fn.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3})

	for v := range vinterx.Map(context.Background(), numbers, func(n int) int {
		return n * 10
	}) {
		fmt.Println(v)
	}
}
Output:
10
20
30

func Reverse

func Reverse[T any](ctx context.Context, seq iter.Seq[T]) iter.Seq[T]

Reverse collects the sequence into memory and yields it in reverse order.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 4, 5})

	for v := range vinterx.Reverse(context.Background(), numbers) {
		fmt.Println(v)
	}
}
Output:
5
4
3
2
1

func Take

func Take[T any](ctx context.Context, seq iter.Seq[T], n int) iter.Seq[T]

Take returns the first n elements.

Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 4, 5})

	for v := range vinterx.Take(context.Background(), numbers, 3) {
		fmt.Println(v)
	}
}
Output:
1
2
3

func TakeWhile

func TakeWhile[T any](ctx context.Context, seq iter.Seq[T], fn func(T) bool) iter.Seq[T]
Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	numbers := slices.Values([]int{1, 2, 3, 0, 4})

	for v := range vinterx.TakeWhile(context.Background(), numbers, func(n int) bool {
		return n > 0
	}) {
		fmt.Println(v)
	}
}
Output:
1
2
3

func Validate

func Validate[T any](ctx context.Context, seq iter.Seq[T], fn func(T) (bool, string), onError func(ValidationError[T])) iter.Seq[T]
Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

type User struct {
	ID     string
	Name   string
	Email  string
	Status string
}

func validateUser(u User) (bool, string) {
	if u.ID == "" {
		return false, "missing ID"
	}
	if u.Name == "" {
		return false, "missing name"
	}
	if u.Email == "" {
		return false, "missing email"
	}
	if u.Status != "active" && u.Status != "inactive" {
		return false, fmt.Sprintf("invalid status: %s", u.Status)
	}
	return true, ""
}

func main() {
	users := slices.Values([]User{
		{ID: "1", Name: "Alice", Email: "alice@example.com", Status: "active"},
		{ID: "", Name: "Bob", Email: "bob@example.com", Status: "inactive"},
		{ID: "3", Name: "Carol", Email: "carol@example.com", Status: "active"},
	})

	for user := range vinterx.Validate(context.Background(), users, validateUser, func(ve vinterx.ValidationError[User]) {
		fmt.Println("invalid:", ve.Reason)
	}) {
		fmt.Println("valid:", user.Name)
	}
}
Output:
valid: Alice
invalid: missing ID
valid: Carol

func Zip

func Zip[A, B any](ctx context.Context, a iter.Seq[A], b iter.Seq[B]) iter.Seq[[2]any]
Example
package main

import (
	"context"
	"fmt"
	"slices"

	vinterx "github.com/MostafaMagdSalama/vortex/interx"
)

func main() {
	left := slices.Values([]int{1, 2, 3})
	right := slices.Values([]string{"a", "b", "c"})

	for pair := range vinterx.Zip(context.Background(), left, right) {
		fmt.Println(pair[0], pair[1])
	}
}
Output:
1 a
2 b
3 c

Types

type ValidateConfig

type ValidateConfig[T any] struct {
	OnError func(ValidationError[T])
}

ValidateConfig controls what happens with invalid items.

type ValidationError

type ValidationError[T any] struct {
	Item   T
	Reason string
}

Jump to

Keyboard shortcuts

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