golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.3k stars 17.58k forks source link

proposal: x/exp/xiter: add Nop, Nop2, Value, Value2 #68947

Open earthboundkid opened 1 month ago

earthboundkid commented 1 month ago

Proposal Details

This could probably go in golang.org/x/exp/xiter for now, but it should also be considered for plain package iter.

Nop yields an empty (no op) sequence. Nop2 yields an empty iter.Seq2.

// Value return an iter.Seq yielding the single value v.
func Value[T any](v T) iter.Seq[T] {
    return func(yield func(T) bool) {
        _ = yield(v)
    }
}

Value2 isn't a great name, but seems the most straightforward.

See #68931, https://github.com/golang/go/issues/65629 and I forget where iter.Value first came up.

timothy-king commented 1 month ago

Quick idea is to generalize to +0 elements. A func Values[T any](v ...T) iter.Seq[T] seems like it could be a decent primitive. Especially for testing/always initializing an iter.Seq. It would cover Nop and Value. Significant overlap with slices.All though.

I am not sure there is a good matching generalization for +0 pairs. maps.All is an okay [but imperfect] substitute for Nop2 and Value2. It requires comparable, and looses order with more elements. Not clear how much these restrictions matter though.

jimmyfrasche commented 1 month ago

In my experiments with iterators I called these (type parameters and packages elided for brevity) Just(T) Seq[T], Just2(K, V) seq2[K, V], and From(...T) Seq[T]. Instead of Nop I went with None. These are all useful in tests and examples. None/None2 in particular kept popping up when implementing other iterators.

earthboundkid commented 1 month ago

xiter has Concat, which can be used for Nop by just doing xiter.Concat[T](). It's not as obvious as it could be though.

josharian commented 5 days ago

Our xiter package contains:

// One returns an iterator that yields the single element x.
func One[T any](x T) iter.Seq[T]

// Empty returns an iterator that yields no values.
func Empty[T any]() iter.Seq[T]

Just more evidence that these are widespread and useful.

Looking through our uses, a single variadic function as proposed by @timothy-king would work fine as well.