2010-01-13 98 views
8
function move() { 

    pos = pos+1; 

    t = setTimeout(move, 100); 
} 

可以称为递归吗?如果是的话,你能否提供任何参考?这可以称为递归吗?

+0

不要把引号的函数名的setTimeout。它绝对不会是递归的,因为函数永远不会被调用,只是引用:-) – 2010-01-13 16:16:45

+1

充其量它可以被称为反复出现:) – 2010-01-26 03:35:39

回答

13

不,递归(func_a调用func_a)或间接递归(func_a调用func_b调用func_a)之间的区别在于,使用定时器进行重复调用将会(不耦合)增长堆栈并丢失以前的状态。

+2

在执行尾部呼叫优化的语言中,这在tail-recursion中是正确的。在Scheme中:'(define(move)(set!pos(+ pos 1))(move))'也不会增长堆栈,但它似乎是递归的。正如我在我的回答中所说的那样,在递归和不是的东西之间并没有真正的界限。 – 2010-01-13 07:25:14

3

否。该函数由外部源(计时器)调用,因此它不是递归的。

+2

不,它*设置*计时器。然后它退出。 – 2010-01-13 07:08:37

+1

这绝对不是递归的。 – ChaosPandion 2010-01-13 07:11:56

0

不,函数不会调用它自己。如果该函数在移动体内自行调用,它将是递归的。

1

所以,这里f1(“move”)正在调用f2(“setTimeout”),后者再次调用f1。嗯..这是一个递归,如果f2是一个回调函数。但是,如果F2正在设置一些属性,如“超时”。这不是递归。

3

它确实取决于您的递归定义,但我会说这是调度一个回调被称为迭代,而不是递归。

递归涉及到将问题分解为更小,类似的问题,直到达到基本案例,然后可能将这些结果合并到解决方案中。这里没有“较小”的问题。它只是安排相同的回调在一定时间后再次发生。

任何种类的硬性和快速定义的问题是递归可以通过迭代来实现,反之亦然。

例如,这是递归吗?

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

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

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

state1state1各自导致另一个被调用;所以从某种意义上说,这是相互递归。它由一个迭代循环驱动,所以它也可以被认为是迭代。

在一种支持尾部优化的语言中,两个函数可以通过递归调用相同的效果(事实上,即使是没有尾部优化的语言,也可以这样做,但是你会用完堆栈空间非常快):

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

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

所以,问题真的变成了,你如何区分是否有某种递归?事实上,一个函数导致自己被再次调用使其递归?

+2

我不认为你的例子显示递归,看起来像一个交替调用的简单循环。没有任何状态是树状遍历所需要的,无论您的状态是堆栈还是显式处理。 – stacker 2010-01-13 07:41:59

+1

然而,在一个有尾部呼叫优化的语言(如Scheme)中,它们基本上是等价的;第二个例子实际上并没有在堆栈上有任何状态,因为尾部调用允许你丢弃前一个堆栈帧。因此,在TCO语言中,尾递归解决方案突然停止递归,因为它不会增加堆栈? – 2010-01-13 07:48:30

+0

你让我了解了tail-call,在我看来,这是不必要地使用递归遍历列表,当且仅当你不需要回到以前的位置(这将需要状态)。 BTW的问题被标记为JavaScript相关。 – stacker 2010-01-13 08:24:47

2

有问题的代码不是递归 - 因为代码被外部调用,而不是作为循环代码路径的一部分返回到相同的方法调用。

维基百科有一个伟大的网页约递归这里:Wikipedia: Recursion (computer science)

0

是的..但它可以被称为间接递归..

例如对于直接递归会是这样的:

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

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

也有人说..函数调用本身..

+0

'setTimeout'不会调用'move'。它只是设置'move'在超时到期并返回时被调用。 – 2010-01-13 16:10:25

+0

马修说什么 – 2010-01-27 08:48:10

2

我把它叫做一个延迟的inifite循环。

当函数返回时,它不会回到它自己的前一个调用实例中,因此没有深层的“调用堆栈”,因为它通常在递归中。

+0

如果函数包含if(pos == 100)dosomething()'?我不认为他是专门针对给定的代码问的。 – 2010-01-13 11:32:29

+0

我认为典型的递归是当你可以说“当这些子任务完成时完成这个任务”。然而,在这种情况下,代码执行它应该做的事情,然后“自行调用”,但没有子任务 - 这是一个循环。代码可能是'while(true){move()} function move(){pos ++}' – naivists 2010-01-13 12:53:01

1

技术上也可能是......

function move() { 

    var $this = this; 

    pos = pos+1; 

    t = setTimeout($this, 100); 
} 

,但我看不出有任何理由,你为什么会想这样做。如果你真的得到傻(并锁定浏览器的线程):

function move() { 

    var now = +new Date; 

    pos = pos+1; 

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

    move(); 
} 
+0

+1谢谢,我只是把清理好的例子放在我的帖子中,因为我不想让人们关注无关码。 – YOU 2010-01-27 08:58:37