views:

365

answers:

10
function move() {

    pos = pos+1;

    t = setTimeout(move, 100); 
}

Can that be called recursive? If yes, could you provide any reference?

Thanks in advance

+3  A: 

No. The function is called by an external source (the timer), so it is not recursive.

Ignacio Vazquez-Abrams
No, it *sets* the timer. And then it exits.
Ignacio Vazquez-Abrams
This is definitely not recursive.
ChaosPandion
A: 

No, the function does not call itself.

Szere Dyeri
+1  A: 

So, here f1 ("move") is calling f2 ("setTimeout"), which in turn calls f1 again. Hmm.. this is a recursion if f2 is a callback function. But, if f2 is setting some property, like a "timeout". This isn't recursion.

Amit
+13  A: 

No, the difference between recursion (func_a calls func_a) or indirect recursion (func_a calls func_b calls func_a) is that using a timer for repetitive calls will (decoupling) not grow the stack and previous state is lost.

stacker
This is true in tail-recursion in a language that performs tail-call optimization. In Scheme: `(define (move) (set! pos (+ pos 1)) (move))` will not grow the stack either, but it certainly seems to be recursive. As I said in my answer, there isn't really a hard line between something that's recursive and something that's not.
Brian Campbell
+3  A: 

It really depends on your definition of recursive, but I would say this is scheduling a callback to be called iteratively, not recursion.

Recursion involves breaking a problem down into smaller, similar problems, until you reach a base case, and then possibly combining the results from those into a solution. There is no "smaller" problem here; it's just scheduling the same callback to happen again after a certain time.

The problem with any sort of hard and fast definition is that recursion can be implemented in terms of iteration, and vice versa.

For instance, is this recursive?

function state1() {
    doSomething();
    return "state2";
}

function state2() {
    doSomethingElse();
    return "state1";
}

var state = "state1";
while (true) {
    if (state == "state1") {
        state = state1();
    } else {
        state = state2();
    }
}

state1 and state1 each cause the other to be called; so in one sense, that's mutual recursion. It's driven by an iterative loop though, so it could also be considered iteration.

In a language that supports tail-call optimization, the same effect could be had by the two functions recursively calling each other (in fact, even in a language without tail-call optimization, you could do it, but you would run out of stack space very quickly):

function state1() {
    doSomething();
    state2();
}

function state2() {
    doSomething();
    state1();
}

So, the question really becomes, how do you distinguish whether something is recursive? Does the fact that one function causes itself to be called again make it recursive?

Brian Campbell
I don't think that your example shows recursion, looks like a simple loop with alternating calls. There is no state as it would be required for tree traversal, either your state is on stack or explicit handled.
stacker
In a language with tail-call optimization (such as Scheme), however, they are basically equivalent; the second example would not actually have any state on the stack either, as tail calls allow you to drop the previous stack frame. So, in a language with TCO, does the tail-recursive solution suddenly stop being recursive because it doesn't grow the stack?
Brian Campbell
You made me learn about tail-call in my opinion this is unneccesary use of recursion like traversing of a list, if and only if you have no need to come back where you were earlier (this would require the state). BTW the question is tagged as javascript related.
stacker
I was not sure it is recursive or not, thats why I only tagged as javascript. thanks a lot for explantions for all anyway.
S.Mark
+2  A: 

The code in question is not recursion - as the code is being called externally, not as part of a cyclic code-path back to the same method call.

Wikipedia has a great page about recursion here: Wikipedia: Recursion (computer science)

Kevin McKelvin
A: 

Yes it is .. but it can be called as Indirect recursion ..

example for Direct recursion would be something like this:

    function factorial (n)
  {
        if(n==0)
   { 
        return(1);
   }

     return (n * factorial (n-1) ); 
  }

likewise others said .. the function calling itself ..

infant programmer
`setTimeout` doesn't call `move`. It just sets up `move` to be called when the timeout expires and returns.
Matthew Crumley
what Matthew said
Dan Beam
+2  A: 

I would call it an inifite loop with a delay.

When the function returns, it does not get back into a previous call instance of itself, hence there is no deep "call stack" as it typically is in recursions.

naivists
What if function contained `if(pos==100) dosomething()` ? I don't think he's asking it specifically for the given code.
ssg
what I see as a typical recursion is when you can say "this task is done when these sub-tasks are done". However, in this case the code performs what it should and then "calls itself", but without subtasking - this is a loop. The code might as well be `while(true) {move()} function move(){pos++}`
naivists
+3  A: 

No. Because you cannot "rewind" the local parameters as you return from called instances. Suppose your code was shaped like this:

function move() {
  var l = pos;
  pos = pos + 1;
  if(pos == 100) return;
  setTimeout("move", 100);
  pos = l;
  alert(pos);
}

You wouldn't be able to get a sequential hierarchy here. However if the code was like this,

function move() {
  var l = pos;
  pos = pos + 1;
  if(pos == 100) return;
  move();
  pos = l;
  alert(pos);
}

you could trace your steps back properly and implement logic based on that. Your code is "not-a-real-recursion" because it can be tail-optimized. Any code that can be tail-optimized is not recursive but iterative in nature. Tail recursion is just a different way of writing a loop.

ssg
+1 thanks, that make sense
S.Mark
+1  A: 

technically it could be...

function move() {

    var $this = this;

    pos = pos+1;

    t = setTimeout($this, 100);
}

but I see no reason why you'd wanna do this. and if you really wanna get silly (and lock up your browser's thread):

function move() {

    var now = +new Date;

    pos = pos+1;

    while( ( +new Date - now ) <= 100 ){ }

    move( );
}
Dan Beam
+1 thanks, I just put cleaned up example at my post, because I don't want people get attention on unrelated codes.
S.Mark