
Donn Cave wrote
But someone who's obliged to use recursive functions to replace the loop-with-mutables functionality he or she is used to, is going to be confronted with some awkward limitations, because loop-with-mutables supports more or less unlimited possibilities, where recursion is (for at least one thing) bound by the need for each iteration to be the same type. That isn't just "you need a new mindset to appreciate this" kind of thing, it's an example of a real obstacle that you just have to learn to get around.
Can you expand on this, because I just don't get it. while Cond do Stmt -- where Vars change in Stmt = loop Vars where loop Vars = if Cond then Stmt;Vars' else Vars Ad hoc definition: *shallow mutation* is replacing the values of entire variables, *deep mutation* is replacing proper parts of variables, *dangerous mutation* is replacing *shared* proper parts of variables. Any loop with shallow mutation can be trivially transliterated to a tail recursion with the same asymptotic cost. Any loop with deep mutation can be trivially transliterated to a tail recursion but with possibly a log(size of data) slowdown -- using uniqueness typing in Clean or monads in Haskell this slowdown can usually be avoided. Any loop with dangerous mutation is asking for trouble in any language, and will be very awkward to express in a functional language, but the problem is the dangerous mutation, not the looping. In imperative languages (such as Dijkstra's notation, Fortran, C, PL/I, C#, D, any of the Algols, Ada, ) I am used to loops where each iteration uses the same body, so I don't understand how this is any less restrictive than a recursion.