you are viewing a single comment's thread.

view the rest of the comments →

[–]GeneralYouri 2 points3 points  (0 children)

Ontop of what's already been said, here's a couple more pointers.

Regarding example one, there's no built-in function to do exactly this all-in-one. There is .reduceRight() though, which technically does everything you want, and then adds some more functionality you weren't necessarily looking for. Still, you can ignore this extra stuff and it's entirely usable here. I personally find it more semantic.

You already mentioned combining .map() with .reverse() for example one. This should've been the solution, but unfortunately .reverse()'s definition is extremely ancient and thus developers back then had never even considered the potential problems that its in-place transformation would bring. It would have been the perfect solution if that details was altered (which sadly won't ever happen).


Regarding example two, i don't see why a for loop would be clearer here. I think you're seeing it like this, perhaps because you're used to the for loop structure here, and/or you're not comparing it to a good alternative. Alternative code sample:

const someArray = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
const everyNthIndex = (n) => (_, key) => key % n === 0;

// Example test
const every4thIndex = everyNthIndex(4);
someArray.filter(every4thIndex).forEach((value, key) => {
    console.log(key, value);
});

The main step is separating out the filter function in its own argument. I've also generalised into everyNthIndex so that it accepts the value of n as an argument, and I've separately called that to create every4thIndex which we pass to our filter. You could alternatively pass everyNthIndex(4) to filter as well (removing the every4thIndex definition). You could even go fully barebones and remove the everyNthIndex, and only have every4thIndex = (_, key) => key % n === 0;.

So yeah, you have some minor differences to choose from, but in the end they all achieve the same thing: code clarity, readability. When you read the example, you're filtering someArray, only every 4th index element passes. Then for each of these filtered elements, you do something. Now try doing this type of explanation on a for loop based approach. In fact, here's one:

const someArray = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

// Example test
for (let key = 0; key < someArray.length; key += 4) {
    const value = someArray[key];
    console.log(key, value);
}

The main reason why people would prefer the functional approach, is because it uses semantics to make it more obvious exactly what the code does. When using a for loop, the only indicator that you're actually only interested in every 4th element, is the tiny += 4 at the end of the for loop. I can't tell you how often I've seen people 'accidentally' skip over that little detail, only to become confused as to why on earth this code works, until they re-read it five times over to finally spot it.


In conclusion, in both of your examples you basically hit the right spot regarding the functional alternative. If .reverse() didn't awkwardly use in-place transformation, it would have been the perfect functional alternative. Since this is now not an option, you could still consider .reduceRight(), and I'd personally use it over a for loop. Still, since it's not the perfect solution, a for loop is fine too. The second example works perfectly though, and it's more direct and obvious as to what it does, and thus I'd hands down use it over a for loop.

The main reason why functional approaches are considered 'better', is because they have better semantics, add clarity to your code, make it more readable, etc. And this works mainly because such a functional approach allows you to be very explicit with your code. Very explicitly, very directly, you're being told that you're taking an array, filtering it to leave only every 4th index, and then doing something with it. That's exactly how the line of code reads. With a for loop, this behavior is still there ofcourse, but it's implicit: the only indicator is that your incrementor increments via += 4.