iter.Pull în Go

Transformă un iterator „push” într-unul „pull”: ceri singur fiecare valoare cu next() și închizi cu stop().

Sintaxă
import "iter"

func Pull[V any](seq Seq[V]) (next func() (V, bool), stop func())
func Pull2[K, V any](seq Seq2[K, V]) (next func() (K, V, bool), stop func())

Ce face iter.Pull

Cu for range, iteratorul decide când îți dă următoarea valoare. iter.Pull(seq) inversează controlul: primești o funcție next(), pe care o apelezi când vrei, și care returnează valoarea și true, sau valoarea zero și false când nu mai sunt valori.

Este necesar când parcurgi două iteratoare în paralel (de exemplu le împerechezi sau le interclasezi), lucru imposibil cu două bucle range. iter.Pull2 face același lucru pentru Seq2 și returnează perechi.

Apelează întotdeauna stop() când ai terminat (de obicei cu defer stop()), ca să eliberezi resursele iteratorului, mai ales dacă nu l-ai parcurs până la capăt.

Parametri

Parametru Descriere
seq Iteratorul transformat.

Ce returnează

Funcțiile next (următoarea valoare și dacă există) și stop (oprește iteratorul).

Exemple

Exemplul 1: Împerecherea a două liste

package main

import (
    "fmt"
    "iter"
    "slices"
)

func main() {
    elevi := []string{"Ana", "Mihai", "Ioana"}
    note := []int{9, 7, 10, 8}

    nextElev, stopElev := iter.Pull(slices.Values(elevi))
    defer stopElev()
    nextNota, stopNota := iter.Pull(slices.Values(note))
    defer stopNota()

    for {
        e, ok1 := nextElev()
        n, ok2 := nextNota()
        if !ok1 || !ok2 {
            break
        }
        fmt.Println(e, n)
    }
}

Rezultat

Ana 9
Mihai 7
Ioana 10

Exemplul 2: Pull2: primele două perechi, apoi stop

package main

import (
    "fmt"
    "iter"
    "slices"
)

func main() {
    orase := []string{"Iași", "Cluj", "Timișoara", "Constanța"}
    next, stop := iter.Pull2(slices.All(orase))
    defer stop()

    for range 2 {
        i, oras, ok := next()
        fmt.Println(i, oras, ok)
    }
    stop()
    i, oras, ok := next()
    fmt.Printf("după stop: %d %q %v\n", i, oras, ok)
}

Rezultat

0 Iași true
1 Cluj true
după stop: 0 "" false

Greșeli frecvente

  • Uiți să apelezi stop() când ieși mai devreme: iteratorul rămâne suspendat și ține memorie ocupată. Pune defer stop() imediat după Pull.
  • Folosești Pull pentru o parcurgere simplă: for range este mai clar și mai rapid.

Comenzi înrudite

  • iter.Seq: Tipurile pentru iteratori: Seq produce valori una câte una, Seq2 produce perechi; ambele se parcurg cu for range.
  • slices.All: Transformă un slice în iterator: All dă perechi (indice, valoare), Values doar valorile, Backward perechile de la coadă la cap.