结果之后不再增加工作
判断是否尾调用,要看调用结果回来之后是否还有事情需要完成,而不是看它是不是源文件最后一行。如果一个函数直接把另一个函数的结果返回,后者可以处于尾位置;若还需把结果加一,这次调用就保留了后续计算,不能仅凭写在return附近就认作尾调用。
为什么可以省去返回层
普通调用需要记住调用者接下来从哪里继续。尾调用的结果将直接交给原来的接收方,因此实现可以避免保存一层只会立即返回的上下文。Scheme要求支持无界数量的活动尾调用;这是一项语言实现保证,而不只是某个编译器碰巧在简单例子上成功做出的优化。
参考:[1]
把待做的工作放进参数
递归求和可以先递归处理剩余元素,再把当前元素加到返回值;这种写法每层都有未完成的加法。另一种安排把已算出的部分和作为参数传下去,递归调用直接给出最终结果。两者表达同一个任务,但控制过程不同;累积参数把原先留在返回途中的工作提前完成。
参考:[2]
控制空间与全部内存不同
尾递归保证关注返回上下文的增长,不承诺整个算法只占固定内存。程序仍可能创建不断变大的列表,或保留大整数和其他数据;非尾递归语言也未必采用同样的优化。因此讨论递归性能时,应同时说明尾位置、实现保证与数据规模,不能把“递归”一词直接等同于栈溢出。