2

In theory, I would like to know a way to have a recursive function that runs forever without exceeding the call stack. I am trying to implement in javascript and I keep getting the error RangeError: Maximum call stack size exceeded

My code looks like this

class mainController{

    static async func1() {
        console.log('Running the Function');
        mainController.func1();
    }

}

Now i expect to just initiate this once in a terminal and let it run forever as long as no error.

I've seen some discussion here JavaScript recursion: Maximum call stack size exceeded which suggests there must be some exit point for the loop. However i want to believe there will be particular application for such infinite loop in setting up things like a daemon process

Arjax
  • 25
  • 5
kenneth_oe
  • 125
  • 1
  • 4
  • 12
  • Did you try setTimeout()? – weroro Mar 04 '23 at 01:17
  • 2
    In general, an unbounded recursive function will end in stack exhaustion. (Technically, tail call optimization can allow for this but it is implementation dependent) This looks like an X-Y problem - you might get better solutions if you describe what you are actually trying to achieve. – David Jones Mar 04 '23 at 01:38
  • To be able to do infinite recursion without exceeding the call stack is called **Tail Call Optimization**. Currently only Safari does it. However you can implement a poor-man's manual tail call optimization using functional (higher level) programming. Check out the 2nd highest voted answer from this question: https://stackoverflow.com/questions/37224520/are-functions-in-javascript-tail-call-optimized (and no, this didn't require setTimeout/setInterval) – slebetman Mar 04 '23 at 02:14
  • infinite stacks do not exist, in other words a stack filling via a recursion without will necessarily reach the limit of the memory stack of any system – Mister Jojo Mar 04 '23 at 03:12

3 Answers3

2

You can keep from overflowing the stack by making the recursive loop async (or, at least, async every few thousand iterations)...

// look in browser console, not in snippet console
const func1 = () => {
  console.log('Running the Function');
  setTimeout(func1);
}
func1();

But

However i want to believe there will be particular application for such infinite loop in setting up things like a daemon process

Such a process is very different from the code above. If you have some code that runs continuously and requires a hack to avoid a stack overflow, you are not really running a background process - you're running a more expensive process that will be taking up a lot of your CPU, and likely interfering with other things you may be doing on that machine. A much more usual background process is passive and is waiting to be triggered by something external (or a timer), rather than running all the time.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
2

There is a difference between a "recursive function" and one "that runs forever". The recursive solution requires an exit case to limit the call stack. Limiting the memory allocation is necessary as a new instance of itself is scoped within its parent. By "runs forever", a simple solution such as while(true){ ... } will call a new instance after the previous call has ended. If you need to remember the details of each iteration, you could use a mapping function... but again, you'd run out of space to put the 1s and 0s.

Arjax
  • 25
  • 5
0

As long as you use setTimeout (or some other way to make each iteration "wait" to be ran by the event loop) then you should be fine:

(() => {
    let i = 0;
    const infinite = () => {
        console.log(i++);
        setTimeout(infinite);
    }
    infinite();
})()
dave
  • 62,300
  • 5
  • 72
  • 93