lo icon indicating copy to clipboard operation
lo copied to clipboard

Any plans to add support for Go 1.23's iterators?

Open BooleanCat opened this issue 1 year ago • 7 comments

Hi there! You're probably aware that Go 1.23 added support for iterators to the standard library with iter.Seq. Many of the features of this library could be adapted to natively support range over functions.

I'd even be happy to work on this feature set. I main go-functional, which is exactly what I described above so many of the iterators from go-functional could be copied over with little modification to support an iter subpackage in this repo for example.

It would support beheaviour like this from go-functional:

for i := range it.Take(it.NaturalNumbers[int](), 3) {
	fmt.Println(i)
}

BooleanCat avatar Aug 28 '24 07:08 BooleanCat

As an example, IndexOf could look like this in a new iter subpackage:

//go:build go1.23

package iter

// IndexOf returns the index at which the first occurrence of a value is found in a sequence or return -1
// if the value cannot be found.
func IndexOf[T comparable](delegate func(func(T) bool), element T) int {
	index := 0

	for item := range delegate {
		if item == element {
			return index
		}

		index++
	}

	return -1
}

(The build constraint will make sure this file is only compiled for folks using Go 1.23 or higher).

BooleanCat avatar Aug 28 '24 08:08 BooleanCat

See #528

BooleanCat avatar Aug 29 '24 08:08 BooleanCat

FWIW, I have written a few of these also, and would be happy to contribute: Map, Flatten (operates over iterators of iterators), FlattenSlice (operates over iterators of slices), FlatMap, FlatMapSlice, Uniq, UniqBy, and Chain.

joel-u410 avatar Sep 03 '24 22:09 joel-u410

I also did some benchmarking, and found that when chaining a few operations (like a couple Maps, then a UniqBy, and a Reduce, etc.) over large collections (e.g. ~100,000) the iterator versions of these were in the vicinity of 10% faster than the slice-based lo equivalents. (And sometimes nearly identical)

I was honestly a little surprised the performance improvement wasn't greater.

joel-u410 avatar Sep 03 '24 22:09 joel-u410

FWIW, I've produced https://github.com/jub0bs/iterutil:

an experimental collection of utility functions (sources, combinators, sinks) for working with Go iterators

jub0bs avatar Sep 24 '24 14:09 jub0bs

@joel-u410

I was honestly a little surprised the performance improvement wasn't greater.

Have you benchmarked heap allocations too? I expect a big difference, esp. for long combinator chains.

jub0bs avatar Sep 24 '24 14:09 jub0bs

I think if we import iter.Seq/iter.Seq2, the implement may be easy, but the performance for inplace operations like Reverse, Replace should drop a lot

dashjay avatar Nov 07 '24 09:11 dashjay

So something I just noticed: iterator variants of First, FirstOr etc. functions would very helpful too.

wrouesnel avatar Oct 11 '25 09:10 wrouesnel

It is available here: it/find.go:387 and it/find.go:406

I'm closing this issue since the initial effort on iterators is done.

Please open new issues for new helpers ;)

samber avatar Oct 12 '25 11:10 samber