let rec f evens odds = function
| [] -> (evens, odds)
| x :: xs ->
if x mod 2 = 0 then f (x :: evens) odds xs
else f evens (x :: odds) xs
OCaml optimizes this fairly well and will compil it down to a single loop with two variables. If you reverse the lists there is going to be additional loops (and corresponding allocations).However OCaml also provides the "tail mod cons" optimization that allows to get some of the benefits of TCO without needing to reverse the list (this is implemented as a program transformation that uses mutability under the hood), and that one will only work if you are building a single list.
The OCaml compiler disagrees with you ;)
It also won't ever turn a cons operation into a dynamic array append.
But sure, in the `fold` scenario where you don't know the number of results in advance (you are more likely to know if you use imperative data structures, e.g. `Hashtbl.length` is constant-time whereas `Map.cardinal` is not), lists might be faster than growing arrays with copies. They are still going to use more memory, and they are unlikely to to be faster than a rope-like structure that grows with no copies.
A parallel `Array.map` still computes a sequence, even though it may not compute in sequence.