For folds over lists you don't need tail call optimization:
You just implement them any which way (eg with loops), and the user of those functions never has to know. That's how eg reduce or map or filter work in Python.
That holds in general for combinators.
Haskell is actually a bad example to use here, because the tail recursive foldl is rarely used. Thanks to laziness, foldr is usually preferred, and it is not tail recursive.
OCaml or Scheme are perhaps better references? Especially given the history of Javascript: the author originally wanted to write a Lisp, but got told by management to add curly braces.
You just implement them any which way (eg with loops), and the user of those functions never has to know. That's how eg reduce or map or filter work in Python.
That holds in general for combinators.
Haskell is actually a bad example to use here, because the tail recursive foldl is rarely used. Thanks to laziness, foldr is usually preferred, and it is not tail recursive.
OCaml or Scheme are perhaps better references? Especially given the history of Javascript: the author originally wanted to write a Lisp, but got told by management to add curly braces.