3 ms·
I think people are going to go off the rails with functions that abstract over for loops. I see it all the time in Javascript code, where people iterate over a
by jrockway 5y ago
I think people are going to go off the rails with functions that abstract over for loops. I see it all the time in Javascript code, where people iterate over an Array multiple times because that's what the API makes easy.
For example, say you want to separate a slice into two slices, one that contains matches and one that contains everything else. Right now, you'd just write:
var matches, mismatches []whatever
for _, x := range xs {
if x == condition {
matches = append(matches, x)
} else {
mismatches = append(mismatches, x)
}
}
But soon, people will be golfing that down to:
matches := slices.Search(xs, func(x whatever) bool { return x == condition })
mismatches := slices.Search(xs, func(x whatever) bool { return x != condition })
This is twice as slow, but it's less lines so I have a feeling that people will have an uncontrollable desire to use it as often as possible. I hope that my feeling is wrong.
(Do note that slices.Search is not a real function yet.)
- TimothyBJacobs 5y agoA common API is something like lodash's `partition` so you don't have to loop over the same Array multiple times: https://lodash.com/docs/#partition https://lodash.com/docs/#partition
- Groxx 5y agoWhile I agree that it'll probably increase, for non-performance-sensitive stuff (or small lists) that doesn't really seem like a problem. And for cases where it is, the answer is the same as it has always been: profile and optimize. Though now it's much easier to make a "matches, mismatches := slices.Split(xs, func(x whatever) bool { return x == condition })" helper, so that improvement even reduces the number of lines further.
- akavi 5y agoGo has multiple return values, so you could instead do: matches, mismatches := slices.Partition(xs, func(x) bool { return x == condition });
- cheriot 5y agoMy experience writing Scala was that there's a modest list of ways people iterate over collections that covers 99.9% of cases. For this example, many languages have a Partition function. matches, mismatches := slices.Partition(xs, func(x whatever) bool { return x == condition })
- Zababa 5y agoThis is a wild guess, but maybe the Search function could be a bit better than expected if it was a bit smarter about allocation size than the regular version you posted. From what I understand, the initial capacity of slices is 0, which would mean that you get a few reallocations with the "naive" version. Search, on the other hand, could allocate a slice with a capacity that's a half of xs, so you only need one reallocation at worst. This, mixed with the "Partition" function proposed by sibling comments (which would only iterate once) could lead to code that's faster than the regular approach, while also being shorter to write. On the other hand, it's not as free as it seems, as now developers have to know the Partition function, and how it works. It may also have pitfalls that I haven't considered. As always, it's hard to find the perfect sweet spot between how much stuff developers should know and how much stuff should be explicit in the code all the time.
- orangecat 5y agoThis is a perfect example of the fundamental and probably irreconcilable disconnect between Go advocates and detractors. To me, your "bad" example is much better: not only is it less code, it directly expresses the intent rather than making the reader infer it from the sequence of manual loops and ifs.