4 ms·
I absolutely love it when we can take advantage of Go's type system and add additional traits and behaviors to existing types like this. That said, I noticed s
by pragma_x 2y ago
I absolutely love it when we can take advantage of Go's type system and add additional traits and behaviors to existing types like this.
That said, I noticed something odd here. In order for a module like this to really shine, I think all these operations need to be functionally pure. Right now, some of these mutate the iterator's `iter` method mid-stream, which is about as side-effect-ful as you can get.
```
func (i Iterator[V]) Map(f func(V) V) Iterator[V] {
cpy := i.iter
i.iter = func(yield func(V) bool) {
for v := range cpy {
v = f(v)
if !yield(v) {
return
}
}
}
return i
}
```
Unless I'm misreading that, `i.iter` has new behavior after this call. A better way would be to return a new _iterator_ with the custom iter behavior instead.
```
func (i Iterator[V]) Map(f func(V) V) Iterator[V] {
// create a fresh iterator around a custom closure (NewIterator() is hypothetical in this case)
return NewIterator(func(yield func(V) bool) {
for v := range i.iter {
v = f(v)
if !yield(v) {
return
}
}
})
}
```
- tantivy 2y agoThis flagged for me right away too. I would be badly surprised if a Map-style chained method mutated the memory of the receiver.
- kunley 2y agoMight be written in a hurry and maybe the author was thinking that not allocating new Iterator, which is in fact wrapper around iter.Seq, will produce less heap garbage. But I guess it's the same amount of garbage, because the size of Iterator is the same as iter.Seq which is allocated anyway, it's just different type of the object being discarded
- relistan 2y agoIf they allocated, people would complain about that. If they don’t, people complain about mutation. :shrug: Personally, the article’s implementation seems fine to me. The iter is a private field of a throwaway struct created on the fly in order to support chaining. If anyone is then relying on the (private) contents of that struct, I think that’s user error. I can’t see personally why you’d do that.