v153 · joint iteration
Laziness, and who gets closed
Three generators standing in for three sensor feeds, each counting what it was asked for and each with a finally block that records when it was shut down. Walk them together and stop early — then check whether the ones you abandoned were closed or simply left open.
Walk three feeds
| step | temperature | humidity | pressure |
|---|---|---|---|
| Not run yet. | |||
Each feed's "pulled" counter increments inside the generator body, and its "closed" flag is set from a finally block. Neither is reported by the zip implementation — they are observations of the generators themselves, which is the only way to tell the difference between an iterator that was closed and one that was merely dropped.
Why the closing matters
A generator that is dropped rather than closed never runs its finally. If that block releases a lock, returns a buffer to a pool, closes a file handle or unsubscribes from a stream, the resource stays held until the generator is collected — which is to say, at a time nobody can predict.
Hand-written zips get this wrong almost universally, because the loop that abandons the longer sequence has no obvious place to call return() on it. The proposal specifies the cleanup for every exit: normal exhaustion, a strict mismatch, and an error thrown by the consumer.