10 ms·
I usually see this pattern as a red flag, but as with anything, there aren't zero legitimate use-cases for it. One use-case is when you lack proper iterators.
by _bxg1 7y ago
I usually see this pattern as a red flag, but as with anything, there aren't zero legitimate use-cases for it.
One use-case is when you lack proper iterators. In JavaScript, the map()/filter() version can be an order of magnitude slower because it's creating and copying a new array at each step. This can be a worthy trade-off for readability in certain cases, but in hot paths converting to the iterate-and-mutate version is one of the most common optimizations I go in and make later on.
Another use-case is readability (sometimes). reduce(), in particular (going from a collection of values to a single value), is notorious for being hard to follow. Of course mapping and filtering are known for usually being very intuitive. But as a baseline, a step-by-step for loop is always a certain degree of kind of intuitive. YMMV, but there are cases where it's the more readable option.
It's probably still worth identifying this as an anti-pattern, so long as you qualify "anti-pattern" with the fact that tradeoffs always need to be considered in context.
- baron816 7y ago> This can be a worthy trade-off for readability in certain cases, but in hot paths... Hot paths aren’t the common case. You should always default to the more readable syntax (map/filter) and then refactor once you’ve determined where your bottlenecks are. Transducers are also an option to get the map/filter syntax without losing and performance, but I think most will unfortunately shy away from those. I do agree that reduce is over used. Reducers as a pattern is really powerful (with transducers), but no one uses them right.
- _bxg1 7y ago> You should always default to the more readable syntax (map/filter) and then refactor once you’ve determined where your bottlenecks are That's exactly what I said: > in hot paths converting to the iterate-and-mutate version is one of the most common optimizations I go in and make later on > Transducers are also an option to get the map/filter syntax without losing and performance All you need are iterators. Python, Rust, Haskell, most languages support performing these functions with iterators. There are even iterator libraries for JS, if you don't mind an extra dependency. But vanilla JS does not support this.
- deleted 7y ago[deleted]
- lloeki 7y agoAdditionally, unless you use a lazy operator, the Ruby code iterates twice, and allocates two arrays. With n > 5 and more chained operations this can get painful. Using lazy enums solves that but may introduce other unsuspected behaviours due to laziness. Still, being reasonably functional can have surprisingly good effects despite extra allocations / iterations.