5 ms·
I don't know why most examples about the Go iterators shows unnecessarily convoluted examples. The authors probably don't know as much of the language as they t
by Seb-C 2y ago
I don't know why most examples about the Go iterators shows unnecessarily convoluted examples. The authors probably don't know as much of the language as they think they do.
Go is far from perfect and certainly has a lot of flaws, but IMO the iterators design fits well into the language and does not deserve the criticism.
The range only needs a function, so what is the point of calling a function that returns a function?
This is enough to make a range iterator, you don't have to call `All` manually:
func (slice Slice) All(yield func(string) bool) {
for _, s := range slice {
if !yield(s) {
break
}
}
}
https://go.dev/play/p/7AYOXzlHU4t?v=gotip https://go.dev/play/p/7AYOXzlHU4t?v=gotip
In Go, the expression `object.method` already returns the method as a function, with `object` being already bound in the scope of the function. The syntax is so that if you have this definition:
type T string
func (t T) f(a int) int {
return a
}
Then:
- `T.f` returns `func(t T, a int) int`
- `T("whatever").f` returns `func(a int) int` where `t` is already set to `"whatever"`
- `T("whatever").f(42)` calls the function and returns `42`
- zachmu 2y agoThis is true, you can just return the method without invoking it. I don't tend to use that convention though, because most of the time when I use this pattern, I'm returning a function that uses a parameter I pass in. You can see this in the predicate example. I prefer keeping my call sites consistent and always using functions that return a function when invoked, rather than sometimes invoking them and sometimes just passing the func reference. YMMV.
- Someone 2y agoThat looks a lot better, indeed. I still don’t understand why every implementation has to do that if in if !yield(s) check, though. Is it ever useful to be able to do something there before returning? If so, wouldn’t it be cleaner to implement this as an interface with two methods, one that simply has to yield for every item produced and an optional one that gets called when the runtime knows it won’t ever run the first one anymore?
- Seb-C 2y agoBecause yield is implemented as a callback, there is no compiler magic to automatically stop the iteration when the caller side uses break or continue, so this condition cannot really be avoided. Also there are many cases where you might need to have some special logic after the last iteration, so simply killing the underlying function is not an option.