Recursion is a natural way to solve some tasks like calculating fibonacci numbers or traversing trees. It's easy to write, read and understand. But it takes more computational resources at run time than solving the same tasks with loops instead of recursion.
For example a loop-based function to find the root of a tree of nodes:
static function getRoot(node:Node):Node { var root = node; while(root.parent != null) { root = root.parent; } return root; }
Its recursive counterpart may look cleaner, but might have worse performance because of additional function calls:
static function getRoot(node:Node):Node { if(node.parent == null) { return node; } return getRoot(node.parent); }
The Haxe compiler since version 4.1.0 can perform automatic recursion-to-loop transformation for functions which end with a recursive call.
This optimization is automatically enabled with the static analyzer (by adding -D analyzer-optimize
to compilation arguments).
Here's how the aforementioned recursive getRoot
function looks in the compiled syntax tree with tail recursion elimination (TRE) enabled:
static function getRoot(node:Node) { while (true) { if (node.parent == null) return node; node = node.parent; } }
The recursive call is automatically replaced with a loop on compilation.
A function must satisfy a number of requirements to be eligible for TRE optimization:
if
or else
expressions.dynamic
accessor.