In Clojure for example you can use the recur especial form to explicit the intention to use non-stack-consuming recursive calls, and is verified by the compiler. As it's wrote in the Clojure docs:
"recur in other than a tail position is an error", "recur is functional and its use in tail-position is verified by the compiler"
In elixir you can define a function as a series of clauses, with recursions calls between them. Is there a way to know for sure that the defined function is going to be tail call optimised?
Compiler doesn't optimize a function. It optimizes a call to that function. It may be the call to the same function inside it, it may be a call to different function, it doesn't matter.
...which isn't the case with Clojure, where recur
can only return execution to the latest "recursion point" (be it loop
or fn
) which makes mutual recursion impossible without "help from the outside", such as a trampoline. It's more like a bandaid than a solution, but the problem is too big and a proper solution would require too much.
Yes, there is a way to make sure it gets optimized in Elixir: it needs to be an actual tail call. That's all.
In computer science, a tail call is a subroutine call performed as the final action of a procedure.
This can easily be determined by visually inspecting the code.
If Clojure were to work this way, the following two definitions would be equivalent:
(defn x [] (x)) ; <- StackOverflowError if called
(defn x [] (recur)) ; <- hangs if called
But if you want to enforce this and fail otherwise, you have to do it either:
The latter seems more practical, easiest with pure functions.
I haven't found any existing solutions that do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With