我似乎误解了尾递归;根据to this stackoverflow question R不支持尾递归。然而,让我们来看看下面的函数来计算第n个斐波纳契数:R中的尾递归
迭代版本:
Fibo <- function(n){
a <- 0
b <- 1
for (i in 1:n){
temp <- b
b <- a
a <- a + temp
}
return(a)
}
“天真”递归版本:
FiboRecur <- function(n){
if (n == 0 || n == 1){
return(n)
} else {
return(FiboRecur(n-1) + FiboRecur(n-2))
}
}
最后一个例子,我发现,应该是尾调用递归:
FiboRecurTail <- function(n){
fib_help <- function(a, b, n){
if(n > 0){
return(fib_help(b, a+b, n-1))
} else {
return(a)
}
}
return(fib_help(0, 1, n))
}
现在,如果我们看看跟踪■当这些函数被调用,这里是我们得到:
Fibo(25)
trace: Fibo(25)
[1] 75025
trace(FiboRecur)
FiboRecur(25)
Thousands of calls to FiboRecur and takes a lot of time to run
FiboRecurTail(25)
trace: FiboRecurTail(25)
[1] 75025
在Fibo(25)
和FiboRecurTail(25)
的情况下,瞬间显示的答案,只有一个调用。对于FiboRecur(25)
,进行了数千次呼叫,并在显示结果之前运行几秒钟。
我们也可以使用benchmark
功能从包装rbenchmark
看看运行时间:
benchmark(Fibo(30), FiboRecur(30), FiboRecurTail(30), replications = 5)
test replications elapsed relative user.self sys.self user.child sys.child
1 Fibo(30) 5 0.00 NA 0.000 0 0 0
2 FiboRecur(30) 5 13.79 NA 13.792 0 0 0
3 FiboRecurTail(30) 5 0.00 NA 0.000 0 0 0
所以,如果R不支持尾递归,什么FiboRecurTail(25)
,使得它运行速度正在发生作为迭代版本,而“天真”递归函数像糖浆一样运行?相反,R支持尾递归,但没有像其他编程语言(例如Haskell)那样优化一个函数的“天真”递归版本作为尾调用递归呢?这是我从这个post in R's mailing list了解到的。
我非常感谢,如果有人会对此有所了解。谢谢!
你说得对,我已经纠正了这一点。 – brodrigues
[R统计环境下的尾递归]可能的重复(http://stackoverflow.com/questions/13208963/tail-recursion-on-r-statistical-environment) –