12 comments

[ 3.8 ms ] story [ 34.2 ms ] thread
Title is a little clickbaity; these are decent examples for where higher order functions may provide more clarity than for loops, but there are also good examples where for loops provide more clarity than higher order functions.

Knowing when to use one or the other is the important bit. Blindly ignoring one of the tools in your toolbox may not be the wisest choice.

Agreed, especially depending on the functional programming background of people involved in a project.

In one project my guideline simply became `for (of)` is welcome, `for (;;)` is not. If you are too busy worried about index numbers as `for (;;)` is, you may be missing the big picture (and doing a lot of "useless" math), `for (of)` at least is relatively high level, and with Iterable support `for (of)` gives you more room to more easily move things out of the loop and into higher-order iterable functions before the loop.

Also with async/await, `for (of)` can sometimes be a lot easier to reckon with than higher order functions. People don't easily grasp Promise combinators, but `for (of) { const thing = await process() }` is readable for most everyone.

Cool story... until you want to BREAK out of the loop.
Wouldn't a while loop be a better option there?

From what I understand the point of a for over a while is that you will iterate for a certain known number of times. But if you aren't doing that (break) isn't the while a better option so you can encapsulate the break in the condition as opposed to random locations in the block.

Say you have 10,000 lines of text, and you want to find the index of the line that contains the 302nd 'U'. You could do this with a while loop, but in the process you would find yourself setting up an index and dutifully incrementing it by 1 to keep track of the line you're currently looking at. A for loop is simpler here.
Wouldn’t a filter() achieve the same result?
No, filter() still visits everything in the list, it just takes a predicate to decide if that item is added to a new list. some() or every() can be used for early termination though.
Well I can't speak for JS, but I use folds with call/cc for this purpose in Scheme.
I agree with the author that performance optimizations for the vast majority of the code we're writing are usually not addressing significant bottlenecks, but they should still include benchmarks.

I put them here: https://jsperf.com/advancedweb-test/1

The for loop executes 20.64x faster in V8.

Again, I think that iterator functions are great and should definitely be used, but it's important to know the cost.

How much of that is because the collection based prime detector has to perform the calculation for every item in the array, even after it's gotten to the 10th item?
I am going to call that wasteful. A for loop has the ability to do most of these things with ONE iteration over a list or array.

Using map/reduce/filter means iterating over each subsequent list, making what could be an O(n) algorithm a lot slower.

I understand the quest for clarity, but one has to consider each case.