[HN Gopher] Pure vs. Impure Iterators in Go
___________________________________________________________________
Pure vs. Impure Iterators in Go
Author : ingve
Score : 39 points
Date : 2025-05-29 08:57 UTC (2 days ago)
(HTM) web link (jub0bs.com)
(TXT) w3m dump (jub0bs.com)
| tapirl wrote:
| Be careful there are bugs and design flaws in Go iterators:
| https://go101.org/blog/2025-03-15-some-facts-about-iterators...
| jub0bs wrote:
| Your post does show that iterators are somewhat of a leaky
| abstraction, but I'm not sure I would go as far as calling some
| of their infelicities "bugs". Whether those infelicities matter
| in practice is a moot point.
| tapirl wrote:
| The bug is confirmed:
| https://github.com/golang/go/issues/71685
| jub0bs wrote:
| Ok, that is annoying. I hope it gets fixed soon.
| euroderf wrote:
| Great! How about iterators on trees ? Multiple options to
| provide.
| pansa2 wrote:
| > _Most iterators provide the ability to walk an entire sequence
| [...] Calling the iterator again walks the sequence again._
|
| > _" Single-use iterators" break that convention, providing the
| ability to walk a sequence only once._
|
| This seems similar to the difference between an "iterable" and an
| "iterator" in Python (and between `IEnumerable` and `IEnumerator`
| in C#).
|
| A Python list `l = [1, 2, 3]` is an _iterable_ , and you can do
| `for v in l: print(v)` multiple times. But `iter(l)` is an
| _iterator_ and `for v in i: print(v)` will only work once.
| catlifeonmars wrote:
| This is the same in JavaScript. There is "pure" Iterable
| protocol which produces an "impure" Iterator. Interestingly ,
| for loops in JavaScript do not work directly with Iterators; to
| use in a for loop you must wrap an Iterator in an Iterable
| codr7 wrote:
| Java is the same if I remember correctly, always felt like a
| design failure to me.
| masklinn wrote:
| It's especially dumb for Java, because Iterator could just
| have been a subtype of Iterable. That's basically what
| Python does, the iterator protocol requires also being an
| iterable[0]. And Rust just blanket implements IntoIterator
| for every Iterator without asking.
|
| At least it's pretty easy to wrap an iterator in JS:
| {[Symbol.iterator]: () => it}
|
| [0] which in the rare case you implement an iterator
| entirely by hand will be a trivial `return self`, so much
| so that `collection.abc.Iterator` just provides that)
| masklinn wrote:
| It's more between repeatable iterables and one-shot iterables
| (of which iterators are a subset, as iterators are iterable).
| For instance a file is an iterable, but (unless it's seekable
| and you rewind it) it'll only let you iterate once.
|
| Basically what Go calls an iterator most other language call an
| iterable. Because it uses internal iteration, Go doesn't hand
| out iterators (save through iter.Pull).
| catlifeonmars wrote:
| - My initial thought is that the performance implication (e.g.
| escaping to the heap) of impure iterators is an implementation
| detail and seems like a good candidate for a future compiler
| optimization.
|
| - impure iterators are strictly more powerful than pure iterators
| in that they _can_ be resumed but do not _have_ to be. If I
| wanted to pick one pattern for consistent behavior across all
| iterators it would be this one.
| gregwebs wrote:
| Not all impure iterators can be resumed. But any pure iterator
| can be converted to a resumable iterator with a generic
| conversion function.
| catlifeonmars wrote:
| > any pure iterator can be converted to a resumable iterator
| with a generic conversion function.
|
| Makes sense
|
| > Not all impure iterators can be resumed
|
| How do you mean? In my head resuming an iterator is just
| partially unrolling a loop.
| nine_k wrote:
| An impure iterator can panic, so you can't resume?
| shubhjain wrote:
| Are the wordings "pure" vs "impure" suitable here, or should it
| have been "stateless" vs "stateful"?
___________________________________________________________________
(page generated 2025-05-31 23:01 UTC)