#+title: for loops considered harmful - tags :: [[file:20210307152738-programming_languages.org][programming languages]] I think I learned this either from [[file:20200705154112-rust.org][Rust]] or [[file:20200604222704-functional_programming.org][functional programming]], but there's an idea that =for= loops are considered harmful. * The danger Consider the following: #+begin_src go days := make([]int, 30) for i = 0; i < 31; i++ { days[i] = i } #+end_src #+RESULTS: 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. #+begin_src js 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); #+end_src #+RESULTS: : [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: #+begin_src js const numbers = [1, 2, 3, 4, 5]; const areEvenOrOdd = numbers.map(v => v % 2 === 0); console.log(areEvenOrOdd); #+end_src #+RESULTS: : [false (\, true) (\, false) (\, true) (\, false)] Mapping, in general, could be implemented as such: #+begin_src js function map(arr, fn) { const res = []; for (let i = 0; i < arr.length; i++) { res[i] = fn(arr[i]); } return res; } #+end_src ** Reduction =reduce= functions are thought of as "summary" or "rollup" functions. One example is adding values. #+begin_src js const numbers = [1, 2, 3, 4, 5]; let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; } console.log(sum); #+end_src #+RESULTS: : 15 : undefined This could be just as easily written as: #+begin_src js const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((sum, val) => sum + val, 0); console.log(sum); #+end_src #+RESULTS: : 15 : undefined This could be generally implemented as: #+begin_src js 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); #+end_src #+RESULTS: : 15 : undefined ** Filtering ** Iterators