DEV Community

Discussion on: Why is using javascript “for loop” for array iteration a bad idea?

 
peerreynders profile image
peerreynders • Edited

filter and reduce would do that and would be clearer.

I took the original comment to have the objectives of:

  • not traversing the entire array (which forEach and filter will do)
  • not creating an intermediate array (which reduce relies on)

There is nothing wrong with the filter/reduce approach, especially if the array is reasonably short (whatever that means in the context of the executing hardware) - and avoiding the intermediate array does require a bit more code

const a = [, 1, , 3, , 5, , 7, , 9, ,];

const result = gatherUntil((v) => v > 6, a); // 1, 3, 5
console.log(`Result: ${result}`); // "Result: 9"

function gatherUntil(p, xs) {
  let result = 0;
  for (let i = 0; i < xs.length; i += 1) {
    if (!xs.hasOwnProperty(i)) continue;

    const value = xs[i];
    if (p(value)) break;

    console.log(i);
    result += value;
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode

But the focus on array HOFs seems to obscure to some people that functions can be composed in a variety of ways.

I also find that in many cases array HOFs make code less readable because the authors insist on using inline, multi-line anonymous functions (forcing a full mental parse of the code) instead of spending a few more lines of code to separate them out and assign them a "Descriptive And Meaningful Name" (related to DAMP) that can be used with the HOF.

Thread Thread
 
_genjudev profile image
Larson • Edited

In my example you could easily write functions for filter and reduce in a declarative way. Which is understandable.

const a = [, 1, , 3, , 5, , 7, , 9, ,];

const isSmallerSix = (n) => n < 6;
const sum = (n, m) => n+m

const result = a.filter( isSmallerSix ).reduce( sum )

console.log(result) // 9
Enter fullscreen mode Exit fullscreen mode

Readability:

  • filter and reduce are much better readable as the gatherUntil function.

Performance (because they all talk about performance in JS)

when was the last time you had performance issue and tought: 'maybe its because of THIS type of loop' in JS?

normally when you write JS you have more performance issues somewhere else as iterating through array's.
Yes, for loops are faster. But you write more code and more code means more bugs. As you can see my little example has just some lines. There is not much space to have a bug here.

Only because something is faster makes it not better for programming, then you wouldn't write JS in first place.

I prefer a more "functional" style of doing things. And would recursion not be so slow (and the stack gets full) in JS i would do that.

and im not quit sure if for loops are slower as reversed while loops.

Thread Thread
 
peerreynders profile image
peerreynders

filter and reduce are much better readable as the gatherUntil function.

Because in this particular case gatherUntil is just as utilitarian as filter and reduce - which still focuses more on the "how" rather than the "why" - declarative or not. Ideally the functions "descriptive and meaningful names" should be more DSL-like, focusing more on the "why" than the "how".

when was the last time you had performance issue and thought: 'maybe its because of THIS type of loop' in JS?

Whenever I start to play around with performance comparisons (example based on this) the good 'ol for…loop seems to perform consistently well across multiple JavaScript engines - while the "other" ways tend to be all over the place.

But you write more code and more code means more bugs.

No Code, no bugs. Other than that studies typically focus on total application length when they state "larger code bases contain more bugs" - but complex applications would be expected to be a.) larger and b.) be more prone to bugs. That doesn't necessarily imply down at the lower level that 1 line is always better than 5 unless this is systemic across the entire code base leading to a significantly larger application. Code Golf emphasizes brevity but tends to lead to code that isn't easy to understand. If there is something to "Code inspection is up to 20 times more efficient than testing" then making code understandable to the broadest possible audience of reviewers is important (within reason - because … trade-offs). Even in A Large-Scale Study of Programming Languages and Code Quality in Github:

However, we caution the reader that even these modest effects might quite possibly be due to other, intangible process factors, for example, the preference of certain personality types for functional, static languages that disallow type confusion.

i.e. as always … it's complicated.

Another argument against "more lines" is that more lines take more time to parse. But not all lines of code are created equal - what matters is the actual workload on the interpreter/compiler during runtime after the parse.

There is not much space to have a bug here.

You did notice that people here expressed surprise about forEach, filter, and reduce skipping holes? Given that processing tends to need to skip undefined values there often isn't a problem - until undefined values and/or the difference between an undefined value and a hole becomes significant. So even on a single line there is space for bugs if code authors/reviewers have an incorrect conceptual model.

Only because something is faster makes it not better for programming, then you wouldn't write JS in first place.

Back in 2009 the video game industry started to abandon OO programming for Data-Oriented Design because OOP imposed too much overhead on commodity hardware. Back then this was largely applied to games written in C/C++ but the trend has lead Unity to adopt DOTS (Data-Oriented Tech Stack) for .NET/C#. Data-Oriented Design aims to optimize for the platform rather than developer experience (ECS - again it's a trade-off).

Similarly I'm imagining JS as running on the shittiest phone out there (on the back end you have other options right?) - the whole Responsible JavaScript thing.

The web is still the most hostile development platform in the world even more so for hyper-constrained devices (Techniques to make a web app load fast,, Setting up a static render in 30 minutes). That level of effort is a far cry from "press of a button, comfy chair development".

I prefer a more "functional" style of doing things.

Sure, but at its core JavaScript is imperative and not as effective at appropriating functional practices as Rust. Most fundamentally it doesn't have "immutability by default" through core-supported, optimized persistent data structures - so mutability is par of the course and it falls to the author to use it responsibly and effectively. I view JavaScript as function-oriented.

And would recursion not be so slow in JS I would do that.

"Slowness" of recursion in JS would be due the "overhead" of the repeated function invocations. You don't seem to be too concerned about the repeated invocations of the functions that are passed to reduce, map, filter etc. (something that could be addressed by putting the logic into a loop body; on the other hand inlining can be tricky). Bounded recursion is doable but simply not optimized for as the for…loop is the most basic (and performant) mode of iteration in JS.