Some functional languages have this convenience. They also usually implement tail call optimizations (convert functions to while loops). This is a helpful feature to have, since it allows easier renaming of functions and makes bugs a little bit more obvious. It’s also more readable.
; Clojure example
(def factorial
(fn [n]
(loop [cnt n
acc 1]
(if (zero? cnt)
acc
(recur (dec cnt) (* acc cnt))
; in loop cnt will take the value (dec cnt)
; and acc will take the value (* acc cnt)
))))
The main reason, as I understand it, for recur is that it refers to calling the same method that it occurs within. That means that you’re guaranteed that the recursion can be transformed into an equivalent iterative definition. Otherwise, a call to the same function might actually dispatch to a different method. So it’s a limitation, rather than a convenience. It would be possible, but it seems like expressing recursion by calling the function is better and more expressive (although harder to do TCO on).
IIUC, Clojure has to workaround the problem that JVM does not have TCO. So I guess it makes sense for Clojure to use recur?
In Julia, I think recurring to the same method makes less sense as the plain for syntax is more idiomatic way to write loops. But it’d be nice to have a syntax for tail-call into different method since, in principle, the compiler can build a finite state machine out of this. This would be more powerful tool than union splitting when writing generic reductions: Tail-call optimization and function-barrier -based accumulation in loops
I fail to see how one can write elegant recursions using for. How do you implement a binary search with for? It seems to me that this needs an ugly while true that manually recurs.