loz

package module
v0.0.0-...-77ec31f Latest Latest
Warning

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

Go to latest
Published: Jan 19, 2026 License: BSD-3-Clause Imports: 4 Imported by: 0

README

Loz

loz is a library for working with Go iterators in a functional style, inspired by samber/lo and standard library functionality in most other languages such as Rust's Iterator, Dart's Iterable, Java's Stream, etc. See also this article, which is not affiliated with this project but explains the motivation for using wrapper types with methods instead of bare functions pretty well.

The name is because it's like lo, but lazy.

Install

go get github.com/jmatth/loz@v1

Usage

loz provides two primary helper types: loz.Seq and loz.KVSeq, which correspond to iter.Seq and iter.Seq2 respectively. You can wrap either of those types directly:

var numsIter iter.Seq[int] = slices.Values([]int{1, 2, 3, 4, 5})
evenNums := loz.Seq[int](numsIter).
	Filter(func(n int) bool { return n%2 == 0 }).
	CollectSlice()
fmt.Println(evenNums)
// Output: [2 4]

var idNameIter iter.Seq2[int, string] = maps.All(map[int]string{
	0:    "root",
	1:    "bin",
	81:   "dbus",
	33:   "http",
	1000: "josh",
	1001: "katie",
})

systemUsers := loz.KVSeq[int, string](idNameIter).
	Filter(func(id int, _ string) bool { return id < 1000 }).
	Values().
	CollectSlice()
fmt.Println(systemUsers)
// Output: [root bin dbus http]

...or use some of the included helpers to create iterators with less code and fewer type annotations:

evenNums := loz.IterSlice([]int{1, 2, 3, 4, 5}).
	Filter(func(n int) bool { return n%2 == 0 }).
	CollectSlice()
fmt.Println(evenNums)
// Output: [2 4]

systemUsers :=
	loz.IterMap(map[int]string{
		0:    "root",
		1:    "bin",
		81:   "dbus",
		33:   "http",
		1000: "josh",
		1001: "katie",
	}).
		Filter(func(id int, _ string) bool { return id < 1000 }).
		Values().
		CollectSlice()
fmt.Println(systemUsers)
// Output: [root bin dbus http]

Mapping

Creating a method to apply a mapping function to all values in a collection presents an interesting challenge in Go. Go's type system does not allow methods to take generic parameters; only functions without a receiver and type definitions can have generic types. To work around this, loz relies on code generation to create a series of types: Map1 through Map9, each of which takes n+1 type parameters, where the first parameter represents the initial type of the elements in the iterator and each successive type represents the type that will be returned by the next call to .Map(). Here is a contrived example:

import (
	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

medians := lom.Map3[string, []string, []int, int](loz.IterSlice([]string{
	"1,2,3",
	"100",
	"3,5",
	"1,6,30,42,70",
})).
	Map(func(s string) []string { return strings.Split(s, ",") }).
	Map(func(sl []string) []int {
		return lom.Map1[string, int](loz.IterSlice(sl)).
			Map(func(s string) int {
				num, err := strconv.Atoi(s)
				if err != nil {
					panic(err)
				}
				return num
			}).
			CollectSlice()
	}).
	Filter(func(nums []int) bool { return len(nums) > 2 && len(nums)%2 != 0 }).
	Map(func(nums []int) int { return nums[len(nums)/2] }).
	CollectSlice()
fmt.Println(medians)
// Output: [2 30]

Similar types exist for KVSeq, named KVMap1 through KVMap9.

A limit of 9 was chosen only because godoc arranges the index lexicographically and having Map10-Map19 sorted before Map2 etc. would make the documentation look even worse than it already does. Realistically you will probably never get close to 9 map operations on a single iterator, but if you have a use case where this is a limitation please open an issue.

Documentation

Overview

Example (FoldWithMap)
package main

import (
	"fmt"

	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

func main() {
	result := lom.Map1[int, string](loz.Generate(5, func(i int) int {
		return i + 1
	})).
		Fold("", func(acc string, n int) string {
			if acc == "" {
				return fmt.Sprintf("%d", n)
			}
			return fmt.Sprintf("%s, %d", acc, n)
		})
	fmt.Printf("%v", result)
}
Output:

1, 2, 3, 4, 5
Example (HaltOnErrorWithMap)
package main

import (
	"fmt"
	"strconv"

	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

func main() {
	nums, err := lom.Map1[string, int](loz.IterSlice([]string{"1", "two", "3"})).
		Map(func(str string) int {
			num, err := strconv.Atoi(str)
			loz.PanicHaltIteration(err)
			return num
		}).
		TryCollectSlice()
	fmt.Printf("%v; %v\n", nums, err)
}
Output:

[]; strconv.Atoi: parsing "two": invalid syntax
Example (SkipOnErrorWithMap)
package main

import (
	"fmt"
	"strconv"

	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

func main() {
	nums := lom.Map1[string, int](loz.IterSlice([]string{"1", "two", "3"})).
		FilterMap(func(num string) (int, bool) {
			res, err := strconv.Atoi(num)
			return res, err == nil
		}).
		CollectSlice()
	fmt.Printf("%v\n", nums)
}
Output:

[1 3]

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func PanicHaltIteration

func PanicHaltIteration(err error)

PanicHaltIteration causes any iteration to end early by wrapping the provided error and panicking. To easily recover from this panic and return the error normally, use a terminal method prefixed with "Try", such as Seq.TryCollectSlice. These methods automatically recover from panics caused by this function and return the wrapped value as their final return value. Calling this method with nil is a noop.

Types

type KVSeq

type KVSeq[K, V any] iter.Seq2[K, V]

KVSeq is an alias to iter.Seq2 that provides additional methods for filtering, transforming, and collecting the elements. Though the name and several doc comments imply it contains key/value pairs, that is only the most common use case and the relationship between the two values is arbitrary.

func IterMap

func IterMap[K comparable, V any](input map[K]V) KVSeq[K, V]

IterMap creates a Seq over the key/value pairs of a map.

func (KVSeq[K, V]) Any

func (s KVSeq[K, V]) Any(test Yielder2[K, V]) bool

Any returns true if test returns true for at least one key/value pair in the iterator, and false otherwise. Returns false for an empty iterator.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/jmatth/loz"
)

func main() {
	seq := loz.IterMap(map[string]string{
		"greeting": "Hello there!",
		"response": "General Kenobi!",
	})
	valsHaveHello := seq.
		Any(func(k, v string) bool {
			return strings.HasPrefix(v, "Hello")
		})
	keysAreShort := seq.Any(func(k, v string) bool {
		return len(k) < 4
	})
	fmt.Printf("%v, %v", valsHaveHello, keysAreShort)
}
Output:

true, false

func (KVSeq[K, V]) Every

func (s KVSeq[K, V]) Every(test Yielder2[K, V]) bool

Every returns true if test returns true for every key/value pair of the iterator, and false otherwise. Returns true for an empty iterator.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/jmatth/loz"
)

func main() {
	seq := loz.IterMap(map[string]string{
		"greeting": "Hello there!",
		"response": "General Kenobi!",
		"followUp": "You are a bold one.",
	})
	allExcitedValues := seq.
		Every(func(k, v string) bool {
			return v[len(v)-1] == '!'
		})
	allLowercaseKeys := seq.Every(func(k, v string) bool {
		return strings.ToLower(k)[0] == k[0]
	})
	fmt.Printf("%v, %v", allExcitedValues, allLowercaseKeys)
}
Output:

false, true

func (KVSeq[K, V]) Filter

func (s KVSeq[K, V]) Filter(filter Yielder2[K, V]) KVSeq[K, V]
Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func toMap[K comparable, V any](seq loz.KVSeq[K, V]) map[K]V {
	return maps.Collect(iter.Seq2[K, V](seq))
}

func main() {
	seq := loz.IterSlice([]string{"zero", "one", "two", "three", "four"}).
		Indexed().
		Filter(func(k int, v string) bool {
			return k%2 != 0 || len(v) == 3
		})
	result := toMap(seq)
	fmt.Printf("%v", result)
}
Output:

map[1:one 2:two 3:three]

func (KVSeq[K, V]) FilterMap

func (s KVSeq[K, V]) FilterMap(mapper func(K, V) (K, V, bool)) KVSeq[K, V]

FilterMap is a combination of KVSeq.Filter and KVSeq.Map. If the provided mapper function returns false, then the current key/value pair of the iteration will be skipped. If true is returned, then the mapped key/value pair is passed to the next iteration stage.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	matching := loz.IterSlice([]int{8, 1, 5, 3}).
		Indexed().
		FilterMap(func(i1, i2 int) (int, int, bool) {
			if i1 != i2 {
				return 0, 0, false
			}
			return i1, i2, true
		}).
		Values().
		CollectSlice()
	fmt.Print(matching)
}
Output:

[1 3]

func (KVSeq[K, V]) First

func (s KVSeq[K, V]) First() (K, V, error)

First consumes the iterator and returns its first key/value pair. If the iterator is empty then zero values will be returned along with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func iterKVPairs[K, V any](kvs ...any) loz.KVSeq[K, V] {
	return func(yield func(K, V) bool) {
		for i := 0; i < len(kvs); i += 2 {
			if !yield(kvs[i].(K), kvs[i+1].(V)) {
				break
			}
		}
	}
}

func main() {
	k, v, err := loz.IterMap(map[int]bool{}).First()
	fmt.Printf("%v, %v, %v\n", k, v, err == nil)
	k, v, err = iterKVPairs[int, bool](1, true, 2, false, 3, true).First()
	fmt.Printf("%v, %v, %v", k, v, err == nil)
}
Output:

0, false, false
1, true, true

func (KVSeq[K, V]) Fold

func (s KVSeq[K, V]) Fold(initialKey K, initialVal V, combine Reducer2[K, V]) (K, V)

Fold reduces the iterator to a single key/value pair by iteratively combining its elements with initial values using the provided function. If the iterator is empty the initial values will be returned unmodified.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	addKMultV := func(k1, v1, k2, v2 int) (int, int) {
		return k1 + k2, v1 * v2
	}
	foldEmptyKey, foldEmptyVal := loz.IterSlice([]int{}).Indexed().Fold(100, 42, addKMultV)
	fmt.Printf("%v, %v\n", foldEmptyKey, foldEmptyVal)
	foldKey, foldVal := loz.IterSlice([]int{2, 4, 2}).Indexed().Fold(0, 1, addKMultV)
	fmt.Printf("%v, %v", foldKey, foldVal)
}
Output:

100, 42
3, 16

func (KVSeq[K, V]) ForEach

func (s KVSeq[K, V]) ForEach(process func(K, V))

ForEach consumes the iterator and calls the provided function with each of the key/value pairs.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func iterKVPairs[K, V any](kvs ...any) loz.KVSeq[K, V] {
	return func(yield func(K, V) bool) {
		for i := 0; i < len(kvs); i += 2 {
			if !yield(kvs[i].(K), kvs[i+1].(V)) {
				break
			}
		}
	}
}

func main() {
	iterKVPairs[int, string](1, "one", 2, "two", 3, "three").
		ForEach(func(k int, v string) {
			fmt.Printf("%v: %v\n", k, v)
		})
}
Output:

1: one
2: two
3: three

func (KVSeq[K, V]) Keys

func (s KVSeq[K, V]) Keys() Seq[K]

ToKeys converts a KVSeq[K, V] to a Seq[K], continuing the iteration with only the keys.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jmatth/loz"
)

func main() {
	keys := loz.IterMap(map[int]string{1: "one", 2: "two", 3: "three"}).
		Keys().
		CollectSlice()
	slices.Sort(keys)
	fmt.Printf("%v", keys)
}
Output:

[1 2 3]

func (KVSeq[K, V]) Last

func (s KVSeq[K, V]) Last() (K, V, error)

Last consumes the iterator and returns its last key/value pair. If the iterator is empty then zero values will be returned along with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func iterKVPairs[K, V any](kvs ...any) loz.KVSeq[K, V] {
	return func(yield func(K, V) bool) {
		for i := 0; i < len(kvs); i += 2 {
			if !yield(kvs[i].(K), kvs[i+1].(V)) {
				break
			}
		}
	}
}

func main() {
	k, v, err := loz.IterMap(map[int]bool{}).Last()
	fmt.Printf("%v, %v, %v\n", k, v, err != nil)
	k, v, err = iterKVPairs[int, bool](1, true, 2, false, 3, true).Last()
	fmt.Printf("%v, %v, %v", k, v, err)
}
Output:

0, false, true
3, true, <nil>

func (KVSeq[K, V]) Map

func (s KVSeq[K, V]) Map(mapper func(K, V) (K, V)) KVSeq[K, V]

Map transforms the key/value pairs within the iterator using the provided mapper function. Due to limitations of the Go type system, the mapped keys and values must be the same types as the input. To perform mapping operations that change types, see [KVMap1], [KVMap2], etc.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func iterKVPairs[K, V any](kvs ...any) loz.KVSeq[K, V] {
	return func(yield func(K, V) bool) {
		for i := 0; i < len(kvs); i += 2 {
			if !yield(kvs[i].(K), kvs[i+1].(V)) {
				break
			}
		}
	}
}

func main() {
	seq := iterKVPairs[int, string](1, "one", 2, "two", 3, "three").
		Map(func(k int, v string) (int, string) {
			return k * 2, v + "+" + v
		})
	result := maps.Collect(iter.Seq2[int, string](seq))
	fmt.Printf("%v", result)
}
Output:

map[2:one+one 4:two+two 6:three+three]

func (KVSeq[K, V]) None

func (s KVSeq[K, V]) None(test Yielder2[K, V]) bool

Every returns true if test returns false for every key/value pair of the iterator, and false otherwise. Returns true for an empty iterator.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/jmatth/loz"
)

func main() {
	seq := loz.IterMap(map[string]string{
		"greeting": "Hello there!",
		"response": "General Kenobi!",
		"followUp": "You are a bold one.",
	})
	noBoredValues := seq.
		None(func(k, v string) bool {
			return v[len(v)-1] != '!'
		})
	noUpperCaseKeys := seq.None(func(k, v string) bool {
		return strings.ToLower(k)[0] != k[0]
	})
	fmt.Printf("%v, %v", noBoredValues, noUpperCaseKeys)
}
Output:

false, true

func (KVSeq[K, V]) Reduce

func (s KVSeq[K, V]) Reduce(combine Reducer2[K, V]) (K, V, error)

Reduce reduces the iterator to a single key/value pair by iteratively combining its elements using the provided function. If the iterator is empty then zero values will be returned along with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	addKMultV := func(k1, v1, k2, v2 int) (int, int) {
		return k1 + k2, v1 * v2
	}
	reducedK, reducedV, err := loz.IterSlice([]int{}).Indexed().Reduce(addKMultV)
	fmt.Printf("%v, %v, %v\n", reducedK, reducedV, err != nil)
	reducedK, reducedV, err = loz.IterSlice([]int{2, 4, 2}).Indexed().Reduce(addKMultV)
	fmt.Printf("%v, %v, %v", reducedK, reducedV, err)
}
Output:

0, 0, true
3, 16, <nil>

func (KVSeq[K, V]) Skip

func (s KVSeq[K, V]) Skip(toSkip int) KVSeq[K, V]

Skip skips the first toSkip key/value pairs of the iterator. If toSkip is greater than or equal to the number of elements in the iterator the result will be an empty iterator.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func toMap[K comparable, V any](seq loz.KVSeq[K, V]) map[K]V {
	return maps.Collect(iter.Seq2[K, V](seq))
}

func main() {
	seq := loz.IterSlice([]string{"zero", "one", "two", "three", "four"}).
		Indexed().
		Skip(3)
	result := toMap(seq)
	fmt.Printf("%v", result)
}
Output:

map[3:three 4:four]

func (KVSeq[K, V]) SkipWhile

func (s KVSeq[K, V]) SkipWhile(test Yielder2[K, V]) KVSeq[K, V]

SkipWhile skips the leading key/value pairs for which test returns true.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func toMap[K comparable, V any](seq loz.KVSeq[K, V]) map[K]V {
	return maps.Collect(iter.Seq2[K, V](seq))
}

func main() {
	seq := loz.IterSlice([]string{"zero", "one", "two", "three", "four"}).
		Indexed().
		SkipWhile(func(k int, v string) bool {
			return k < 3
		})
	result := toMap(seq)
	fmt.Printf("%v", result)
}
Output:

map[3:three 4:four]

func (KVSeq[K, V]) Take

func (s KVSeq[K, V]) Take(toTake int) KVSeq[K, V]

Take restricts the iterator to at most the first toTake key/value pairs.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func toMap[K comparable, V any](seq loz.KVSeq[K, V]) map[K]V {
	return maps.Collect(iter.Seq2[K, V](seq))
}

func main() {
	seq := loz.IterSlice([]string{"zero", "one", "two", "three", "four"}).
		Indexed().
		Take(2)
	result := toMap(seq)
	fmt.Printf("%v", result)
}
Output:

map[0:zero 1:one]

func (KVSeq[K, V]) TakeWhile

func (s KVSeq[K, V]) TakeWhile(test Yielder2[K, V]) KVSeq[K, V]

TakeWhile restricts the iterator to the leading key/value pairs for which test returns true.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/jmatth/loz"
)

func toMap[K comparable, V any](seq loz.KVSeq[K, V]) map[K]V {
	return maps.Collect(iter.Seq2[K, V](seq))
}

func main() {
	seq := loz.IterSlice([]string{"zero", "one", "two", "three", "four"}).
		Indexed().
		TakeWhile(func(k int, v string) bool {
			return k < 3
		})
	result := toMap(seq)
	fmt.Printf("%v", result)
}
Output:

map[0:zero 1:one 2:two]

func (KVSeq[K, V]) TryAny

func (s KVSeq[K, V]) TryAny(test Yielder2[K, V]) (_ bool, err error)

TryAny is identical to KVSeq.Any, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryEvery

func (s KVSeq[K, V]) TryEvery(test Yielder2[K, V]) (_ bool, err error)

TryEvery is identical to KVSeq.Every, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryFirst

func (s KVSeq[K, V]) TryFirst() (_ K, _ V, err error)

TryFirst is identical to KVSeq.First, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryFold

func (s KVSeq[K, V]) TryFold(initialKey K, initialVal V, combine Reducer2[K, V]) (_ K, _ V, err error)

TryFold is identical to KVSeq.Fold, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryForEach

func (s KVSeq[K, V]) TryForEach(process func(K, V)) (err error)

TryForEach is identical to KVSeq.ForEach, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryLast

func (s KVSeq[K, V]) TryLast() (_ K, _ V, err error)

TryLast is identical to KVSeq.Last, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryNone

func (s KVSeq[K, V]) TryNone(test Yielder2[K, V]) (_ bool, err error)

TryNone is identical to KVSeq.None, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) TryReduce

func (s KVSeq[K, V]) TryReduce(combine Reducer2[K, V]) (_ K, _ V, err error)

TryReduce is identical to [KVSeq.ForReduce], except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (KVSeq[K, V]) Values

func (s KVSeq[K, V]) Values() Seq[V]

Values converts a KVSeq[K, V] to a Seq[V], continuing the iteration with only the values.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jmatth/loz"
)

func main() {
	vals := loz.IterMap(map[int]string{1: "one", 2: "two", 3: "three"}).
		Values().
		CollectSlice()
	slices.Sort(vals)
	fmt.Printf("%v", vals)
}
Output:

[one three two]

type Seq

type Seq[V any] iter.Seq[V]

Seq is an alias to iter.Seq that provides additional methods for filtering, transforming, and collecting the elements.

Example (ErrorHandling)
package main

import (
	"fmt"
	"strconv"

	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

func main() {
	result, err := lom.Map1[string, int](loz.IterSlice([]string{"1", "foo", "3"})).
		Map(func(s string) int {
			num, err := strconv.Atoi(s)
			loz.PanicHaltIteration(err)
			return num
		}).TryCollectSlice()
	fmt.Printf("%v; %v", result, err)
}
Output:

[]; strconv.Atoi: parsing "foo": invalid syntax
Example (IncorrectErrorHandling)
package main

import (
	"fmt"
	"strconv"

	"github.com/jmatth/loz"
	lom "github.com/jmatth/loz/mapping"
)

func main() {
	defer func() {
		r := recover()
		if r != nil {
			fmt.Printf("example code panicked: %v", r)
		}
	}()

	result, err := lom.Map1[string, int](loz.IterSlice([]string{"1", "foo", "3"})).
		Map(func(s string) int {
			num, err := strconv.Atoi(s)
			if err != nil {
				panic(err)
			}
			return num
		}).TryCollectSlice()
	fmt.Printf("%v; %v", result, err)
}
Output:

example code panicked: strconv.Atoi: parsing "foo": invalid syntax

func Generate

func Generate[V any](count int, generator func(idx int) V) Seq[V]

Generate creates a Seq by calling the provided generator with [0, count). A count < 1 yields an empty iterator.

func IterSlice

func IterSlice[V any](slice []V) Seq[V]

IterSlice creates a Seq over the contents of a slice.

func (Seq[V]) Any

func (s Seq[V]) Any(test Yielder[V]) bool

Any returns true if test returns true for at least one element in the iterator, and false otherwise. Returns false for an empty iterator.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	isEven := func(n int) bool {
		return n%2 == 0
	}
	isBig := func(n int) bool {
		return n > 9_000
	}

	nums := []int{1, 3, 7, 9_001}
	anyEven := loz.IterSlice(nums).Any(isEven)
	anyBig := loz.IterSlice(nums).Any(isBig)
	fmt.Printf("%v, %v", anyEven, anyBig)
}
Output:

false, true

func (Seq[V]) AppendSlice

func (s Seq[V]) AppendSlice(slice *[]V)
Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	s := make([]int, 0, 5)
	s = append(s, 1, 2)
	loz.Generate(3, func(idx int) int {
		return idx + 3
	}).AppendSlice(&s)
	fmt.Print(s)
}
Output:

[1 2 3 4 5]

func (Seq[V]) CollectSlice

func (s Seq[V]) CollectSlice() []V

CollectSlice collects all the elements within the iterator into a slice by calling slices.Collect.

func (Seq[V]) Every

func (s Seq[V]) Every(test Yielder[V]) bool

Every returns true if test returns true for every element of the iterator, and false otherwise. Returns true for an empty iterator.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	isOdd := func(n int) bool {
		return n%2 != 0
	}
	isBig := func(n int) bool {
		return n > 9_000
	}

	nums := []int{1, 3, 7, 9_001}
	anyEven := loz.IterSlice(nums).Every(isOdd)
	anyBig := loz.IterSlice(nums).Every(isBig)
	fmt.Printf("%v, %v", anyEven, anyBig)
}
Output:

true, false

func (Seq[V]) Expand

func (s Seq[V]) Expand(toElements Mapper[V, Seq[V]]) Seq[V]
Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	expander := func(n int) loz.Seq[int] {
		return func(yield func(int) bool) {
			for i := range n {
				if !yield(i + 1) {
					break
				}
			}
		}
	}

	nums := []int{1, 2, 3, 0, 5}
	expanded := loz.IterSlice(nums).Expand(expander).CollectSlice()
	fmt.Printf("%v", expanded)
}
Output:

[1 1 2 1 2 3 1 2 3 4 5]

func (Seq[V]) Filter

func (s Seq[V]) Filter(filter Yielder[V]) Seq[V]

Filter filters the iterator to only include only elements for which filter returns true.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	filteredSlice := loz.IterSlice([]bool{true, false, true, false, true}).
		Filter(
			func(b bool) bool {
				return !b
			}).CollectSlice()
	fmt.Printf("%v", filteredSlice)
}
Output:

[false false]

func (Seq[V]) FilterMap

func (s Seq[V]) FilterMap(mapper FilteringMapper[V, V]) Seq[V]

FilterMap is a combination of Seq.Filter and Seq.Map. If the provided mapper function returns false, then the current element of the iteration will be skipped. If true is returned, then the mapped value is passed to the next iteration stage.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	matching := loz.IterSlice([]int{0, 10, 2, 3, 44, 55}).
		FilterMap(func(i int) (int, bool) {
			if i < 10 {
				return 0, false
			}
			return i / 10, true
		}).
		CollectSlice()
	fmt.Print(matching)
}
Output:

[1 4 5]

func (Seq[V]) First

func (s Seq[V]) First() (V, error)

First consumes the iterator and returns its first element. If the iterator is empty a zero value will be returned with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	first, err := loz.IterSlice([]int{}).First()
	fmt.Printf("%v, %v\n", first, err != nil)
	first, err = loz.IterSlice([]int{1, 2, 3}).First()
	fmt.Printf("%v, %v", first, err)
}
Output:

0, true
1, <nil>

func (Seq[V]) Fold

func (s Seq[V]) Fold(initial V, combine Reducer[V, V]) V

Fold reduces the iterator to a single value by iteratively combining its elements with an initial value using the provided function. If the iterator is empty the initial value will be returned unmodified.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	mult := func(a, b int) int {
		return a * b
	}
	foldEmpty := loz.IterSlice([]int{}).Fold(100, mult)
	foldVals := loz.IterSlice([]int{2, 4, 2}).Fold(1, mult)
	fmt.Printf("%v, %v", foldEmpty, foldVals)
}
Output:

100, 16

func (Seq[V]) ForEach

func (s Seq[V]) ForEach(process Processor[V])

ForEach consumes the iterator and calls the provided function with each of the elements.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	loz.IterSlice([]int{1, 2, 3}).ForEach(func(i int) {
		fmt.Printf("(%v)", i)
	})
}
Output:

(1)(2)(3)

func (Seq[V]) Indexed

func (s Seq[V]) Indexed() KVSeq[int, V]

func (Seq[V]) Last

func (s Seq[V]) Last() (V, error)

Last consumes the iterator and returns its last element. If the iterator is empty a zero value will be returned with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	first, err := loz.IterSlice([]int{}).Last()
	fmt.Printf("%v, %v\n", first, err != nil)
	first, err = loz.IterSlice([]int{1, 2, 3}).Last()
	fmt.Printf("%v, %v", first, err)
}
Output:

0, true
3, <nil>

func (Seq[V]) Map

func (s Seq[V]) Map(mapper Mapper[V, V]) Seq[V]

Map transforms the elements within the iterator using the provided mapper function. Due to limitations of the Go type system, the mapped value must be the same type as the input. To perform mapping operations that change type, see [Map1], [Map2], etc.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	nums := []int{1, 2, 3}
	doubled := loz.IterSlice(nums).Map(func(n int) int { return n * 2 }).CollectSlice()
	fmt.Printf("%v", doubled)
}
Output:

[2 4 6]

func (Seq[V]) None

func (s Seq[V]) None(test Yielder[V]) bool

Every returns true if test returns false for every element of the iterator, and false otherwise. Returns true for an empty iterator.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	isEven := func(n int) bool {
		return n%2 == 0
	}
	isBig := func(n int) bool {
		return n > 9_000
	}

	nums := []int{1, 3, 7, 9_001}
	anyEven := loz.IterSlice(nums).None(isEven)
	anyBig := loz.IterSlice(nums).None(isBig)
	fmt.Printf("%v, %v", anyEven, anyBig)
}
Output:

true, false

func (Seq[V]) Reduce

func (s Seq[V]) Reduce(combine Reducer[V, V]) (V, error)

Reduce reduces the iterator to a single value by iteratively combining its elements using the provided function. If the iterator is empty a zero value will be returned along with an error.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	mult := func(a, b int) int {
		return a * b
	}
	reduced, err := loz.IterSlice([]int{}).Reduce(mult)
	fmt.Printf("%v, %v\n", reduced, err != nil)
	reduced, err = loz.IterSlice([]int{2, 4, 2}).Reduce(mult)
	fmt.Printf("%v, %v\n", reduced, err)
}
Output:

0, true
16, <nil>

func (Seq[V]) Skip

func (s Seq[V]) Skip(toSkip int) Seq[V]

Skip skips the first toSkip elements of the iterator. If toSkip is greater than or equal to the number of elements in the iterator the result will be an empty iterator.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	skipped := loz.IterSlice(nums).Skip(3).CollectSlice()
	fmt.Printf("%v", skipped)
}
Output:

[4 5 6 7 8 9]

func (Seq[V]) SkipWhile

func (s Seq[V]) SkipWhile(test Yielder[V]) Seq[V]

SkipWhile skips the leading elements for which test returns true.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	result := loz.IterSlice([]int{2, 4, 5, 6, 8}).
		SkipWhile(func(n int) bool { return n%2 == 0 }).
		CollectSlice()
	fmt.Printf("%v", result)
}
Output:

[5 6 8]

func (Seq[V]) Take

func (s Seq[V]) Take(toTake int) Seq[V]

Take restricts the iterator to at most the first toTake elements.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	took := loz.IterSlice(nums).Take(3).CollectSlice()
	fmt.Printf("%v", took)
}
Output:

[1 2 3]

func (Seq[V]) TakeWhile

func (s Seq[V]) TakeWhile(test Yielder[V]) Seq[V]

TakeWhile restricts the iterator to the leading elements for which test returns true.

Example
package main

import (
	"fmt"

	"github.com/jmatth/loz"
)

func main() {
	result := loz.IterSlice([]int{2, 4, 5, 6, 8}).
		TakeWhile(func(n int) bool { return n%2 == 0 }).
		CollectSlice()
	fmt.Printf("%v", result)
}
Output:

[2 4]

func (Seq[V]) TryAny

func (s Seq[V]) TryAny(test Yielder[V]) (result bool, err error)

TryAny is identical to Seq.Any, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryCollectSlice

func (s Seq[V]) TryCollectSlice() (result []V, err error)

TryCollectSlice is identical to Seq.CollectSlice, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryEvery

func (s Seq[V]) TryEvery(test Yielder[V]) (result bool, err error)

TryEvery is identical to Seq.Every, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryFirst

func (s Seq[V]) TryFirst() (result V, err error)

TryFirst is identical to Seq.First, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryFold

func (s Seq[V]) TryFold(initial V, combine Reducer[V, V]) (result V, err error)

TryFold is identical to Seq.Fold, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryForEach

func (s Seq[V]) TryForEach(process Processor[V]) (err error)

TryForEach is identical to Seq.ForEach, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryLast

func (s Seq[V]) TryLast() (result V, err error)

TryLast is identical to Seq.Last, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryNone

func (s Seq[V]) TryNone(test Yielder[V]) (result bool, err error)

TryNone is identical to Seq.None, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

func (Seq[V]) TryReduce

func (s Seq[V]) TryReduce(combine Reducer[V, V]) (result V, err error)

TryReduce is identical to Seq.Reduce, except it will recover any panic caused by PanicHaltIteration and return the wrapped error.

type SeqError

type SeqError int
const (
	EmptySeqErr SeqError = iota
)

func (SeqError) Error

func (e SeqError) Error() string

Directories

Path Synopsis
Package mapping provides additional wrapper types for loz.Seq and loz.KVSeq so that methods can change the type of the elements in the iterator.
Package mapping provides additional wrapper types for loz.Seq and loz.KVSeq so that methods can change the type of the elements in the iterator.

Jump to

Keyboard shortcuts

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