from garden/ryan/20210507122748for_loops_considered_harmful.org by @ryan

tags :: programming languages
I think I learned this either from Rustor functional programming but there's
an idea that for
loops are considered harmful.
The danger
Consider the following:
days := make([]int, 30) for i = 0; i < 31; i++ { days[i] = i }
This is a banal example, but this code introduces the possibility for an indexing error.
The solution
There are a few ways to mitigate these problems.
Mapping
Most for loops you see in the wild are just mappings of some kind or another. Mapping is when you want a 1:1 derivation of a new value from an old value.
const numbers = [1, 2, 3, 4, 5]; const areOddOrEven = []; for (let i = 0; i < numbers.length; i++) { areOddOrEven[i] = numbers[i] % 2 === 0; } console.log(areOddOrEven);
[false (\, true) (\, false) (\, true) (\, false)]
This example is a mapping from number to bool, where what we're mapping is whether or not a number is even. It could be rewritten as:
const numbers = [1, 2, 3, 4, 5]; const areEvenOrOdd = numbers.map(v => v % 2 === 0); console.log(areEvenOrOdd);
[false (\, true) (\, false) (\, true) (\, false)]
Mapping, in general, could be implemented as such:
function map(arr, fn) { const res = []; for (let i = 0; i < arr.length; i++) { res[i] = fn(arr[i]); } return res; }
Reduction
reduce
functions are thought of as "summary" or "rollup" functions.
One example is adding values.
const numbers = [1, 2, 3, 4, 5]; let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; } console.log(sum);
15 undefined
This could be just as easily written as:
const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((sum, val) => sum + val, 0); console.log(sum);
15 undefined
This could be generally implemented as:
function reduce(coll, fn, init) { let res = init; for (let i = 0; i < coll.length; i++) { res = fn(res, coll[i]); } return res; } const numbers = [1, 2, 3, 4, 5]; const sum = reduce(numbers, (sum, val) => sum + val, 0); console.log(sum);
15 undefined