我们在上一章的复习讲座中已经提到了Scheme中的递归调用。我们熟悉C/C++或Java等命令式编程语言的朋友对递归应该不陌生吧,呵呵。我们本讲将介绍一下Scheme中的递归调用。
作为一个函数式编程语言,其优美的地方就是用了很多递归实现。在函数式编程语言中,递归比一般的迭代用得更多。由于函数式编程语言最初都是解释执行的,因此对函数的调用有尾调用(Tail Call)的实现,从而对过程调用的数目与存储器占用的关系不是线性递增的关系,而是常量关系。即,Scheme总能在常量空间中执行迭代型计算要求。
这里先简单讲讲什么是尾调用。
在计算机科学中,一个尾调用是一个产生返回值的子例程调用。也就是说,一个过程通过调用另一个子例程后被直接返回,那么我们称对那个子例程的调用是一个尾调用。比如:
我们看到上述一个C代码,proc中对inc子例程的调用就是尾调用。因为,调用inc后,其返回值也立即作为proc的返回值被返回。
我们可以再看一些例子:
另外,如果一个过程中有分支,并且在分支中最后也是通过调用一个子例程后直接返回,那么对该子例程的调用也是尾调用的,呵呵。
如果一次尾调用是调用者自己,那么称这个尾调用是尾递归。
下面进入正题,我们先看最典型的递归——阶乘:
其实有了前面的基础,用Scheme写递归看上去比用C写更容易些,呵呵。