- 递归
在自己的定义中调用自己的函数叫做递归函数(Recursive Function)。
(define (fact n)
(if (= n 1)
1
(* n (fact (- n 1)))))
(define (list*2 ls)
(if (null? ls)
'()
(cons (* 2 (car ls))
(list*2 (cdr ls)))))
- 尾递归
普通的递归调用并不高效因为它既浪费存储空间又具有函数调用开销。与之相反,尾递归函数包含了计算结果,当计算结束时直接将其返回。特别地,由于Scheme规范要求尾递归调用转化为循环,因此尾递归调用就不存在函数调用开销。
(define (fact-tail n)
(fact-rec n n))
(define (fact-rec n p)
(if (= n 1)
p
(let ((m (- n 1)))
(fact-rec m (* p m)))))
- 命名let
命名let(named let)可以用来表达循环。[代码片段3]中的函数fact-let展示了如何使用命名let来计算阶乘。fact-let函数使用了一个命名let表达式(loop),这与在[代码片段2]中展示的fact-rec函数是不同的。在被注释为;1的那行,代码将参数n1和p都初始化为n。再每次循环后,参数在被注释为;2的那行更新:将n1减1,而将p乘以(n1 - 1)。
在Scheme中,用命名let来表达循环是俗成的方法。
(define (fact-let n)
(let loop((n1 n) (p n)) ; 1
(if (= n1 1)
p
(let ((m (- n1 1)))
(loop m (* p m)))))) ; 2
- letrec
(define (fact-letrec n)
(letrec ((iter (lambda (n1 p)
(if (= n1 1)
p
(let ((m (- n1 1)))
(iter m (* p m))))))) ; *
(iter n n)))
- do表达式
网友评论