HN
Today

Removing recursion via explicit callstack simulation

This technical deep dive explores a systematic, albeit verbose, method to eliminate recursion from TypeScript code by explicitly simulating the call stack. It addresses the common Node.js stack overflow problem, providing a practical, tested solution for developers facing deep recursion. The article is valuable on HN for its detailed technical explanation, performance analysis, and robust verification using property-based testing.

3
Score
0
Comments
#23
Highest Rank
3h
on Front Page
First Seen
Mar 13, 5:00 PM
Last Seen
Mar 13, 7:00 PM
Rank Over Time
233028

The Lowdown

The author presents a method for manually converting elegant recursive functions into gnarled imperative forms to achieve stack safety, particularly relevant in environments like Node.js where deep recursion can lead to stack overflows. This technique trades clarity and some performance for robustness by explicitly simulating the language's call stack.

  • The post begins with simple examples, like summing a linked list, to illustrate cases where recursion can be easily replaced by iteration due to associativity and data structure simplicity.
  • It then moves to binary tree summation, showing how branching data structures necessitate an explicit stack for iterative traversal, introducing the concept of "reifying execution."
  • A complex, mutually-recursive Tree<T> and Forest<T> data structure is introduced to demonstrate a scenario where intuitive iterative conversion is difficult, thus necessitating a methodical approach.
  • The core technique involves defining explicit StackFrame types (e.g., FoldTreeFrame, FoldForestFrame) that mirror a function's arguments, child calls, return values, and parent frames.
  • An iterative loop then processes these frames, simulating recursive calls by creating new frames and returns by updating a returnValue and moving to the parent frame. Memory management, by nulling out child references, is also discussed.
  • The correctness of this verbose iterative solution is verified using property-based testing with fast-check, comparing its output against the simpler recursive reference for a wide range of randomly generated inputs.
  • Performance benchmarks indicate that the iterative solution is approximately 2.2 times slower than its recursive counterpart, a trade-off deemed acceptable for ensuring stack safety.
  • Limitations of the approach are discussed, specifically its inapplicability to polymorphically-recursive functions where stack frame types would dynamically change.

Ultimately, the article provides a detailed, systematic guide for transforming recursive algorithms into stack-safe iterative ones, emphasizing the crucial role of property-based testing in validating the correctness of such complex transformations for production-grade code.