Question about iter.Seq & iter.Pull

474 views
Skip to first unread message

Miki Tebeka

unread,
Mar 14, 2024, 10:45:39 AM3/14/24
to golang-dev
Hi,

I'm writing the following Max function:

func Max[T cmp.Ordered](seq iter.Seq[T]) (T, error) {
pull, stop := iter.Pull(seq)
defer stop()

m, ok := pull()
if !ok {
return m, fmt.Errorf("Max of empty sequence")
}
fmt.Println(">>> m:", m)

for v := range seq {
fmt.Println(">>> v:", v)
if v > m {
m = v
}
}

return m, nil
}

When I run it (see https://go.dev/play/p/9kkQUj3wZiV), I see that "m" and the first "v" are the same. It's like the iterator is restarted.

When I use pull instead of the "range seq", I don't see the first value twice.

    for v, ok := pull(); ok; v, ok = pull() {

Is that the intended behaviour or a bug?

Thanks,
Miki

Ian Lance Taylor

unread,
Mar 14, 2024, 3:47:26 PM3/14/24
to Miki Tebeka, golang-dev
On Thu, Mar 14, 2024 at 7:45 AM Miki Tebeka <miki....@gmail.com> wrote:
>
> I'm writing the following Max function:
>
> func Max[T cmp.Ordered](seq iter.Seq[T]) (T, error) {
> pull, stop := iter.Pull(seq)
> defer stop()
>
> m, ok := pull()
> if !ok {
> return m, fmt.Errorf("Max of empty sequence")
> }
> fmt.Println(">>> m:", m)
>
> for v := range seq {
> fmt.Println(">>> v:", v)
> if v > m {
> m = v
> }
> }
>
> return m, nil
> }
>
> When I run it (see https://go.dev/play/p/9kkQUj3wZiV), I see that "m" and the first "v" are the same. It's like the iterator is restarted.

You have one iteration that uses pull (once) and one iteration that
ranges over seq. Those are two independent iterations, so naturally
they both see the first element.

Ian

Miki Tebeka

unread,
Mar 17, 2024, 11:03:34 AM3/17/24
to Ian Lance Taylor, golang-dev
Thanks Ian.

Those are two independent iterations, so naturally they both see the first element.
Coming from Python, this is different - that's what confused me. 

Ethan Reesor

unread,
Mar 17, 2024, 3:00:26 PM3/17/24
to Ian Lance Taylor, Miki Tebeka, golang-dev
`seq` is a function that iterates, yielding values via the callback. `seq` presumably does not have state. Each time you call it, it iterates. Of course you could write an iterator that maintained state, but personally I would expect `func(yield func(V) bool)` not to retain state between invocations.

On the other hand, a push iterator defined as `var next func() (V, bool)` must have state, otherwise it would not be able to iterate.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-dev/CACjPmS2hP30WBpiaQnXzApUb5QEjh%3DtrwJhQSa%3DCSN_2_2WyrA%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages