I agree with the sentiment, but not with Go's interpretation. To me, higher-order functions like map and reduce are much easier to read than the equivalent for loops and are less likely to have subtle bugs (off-by-one errors, etc.) because they more directly capture the author's intent.
In my experience, loops and recursion are lower level constructs that should ideally be used only in libraries (map, filter, limit, sum, distinct, etc [1]) and in hot code paths (for optimization).
Kevlin Henney makes a good observation on one of his talks about how "you have written all the loops you will never need in your life" [2], and those are constructs such as map/filterand friends, present in LINQ, Java Streams, Ruby Enumerables, etc.
His argument is that code made with those primitive is clearer than code made than procedural loops, because when you read it you don't have to "execute the code in your head".
I'd argue that using procedural loops is what's actually "too clever" here, despite being more verbose!
-
[1] I have mixed feelings about "Reduce". It is hard to use and, most of the time, hard to read as well. It's too low-level.
I have mixed feelings about "Reduce". It is hard to use and, most of the time, hard to read as well. It's too low-level.
Fair enough. I'd certainly always prefer a special case like `.sum()` over something like `.reduce((a, b) => a + b, 0)` where applicable.
I don't think reduce is overly complicated, but it's not much of a step up over a for loop and can be abused to write code that's more confusing to reason about than an equivalent loop.