我相信这是独立的实现,但我在debian上使用clisp。
下面我定义了两个名为SUM
的函数。他们通过向N2添加1并从N1减去1直到N1为0来找到两个非负整数的总和。方法#1对我有意义,但方法#2是混乱的来源。
;;;Approach #1 (I understand why it works)
> (defun sum (n1 n2) "Return the sum of two nonnegative integers."
(if (zerop n1) n2 (sum (1- n1) (1+ n2)))) ;1+ adds 1 to it's operator
> (sum 5 10)
1. Trace: (SUM '5 '10)
2. Trace: (SUM '4 '11)
3. Trace: (SUM '3 '12)
4. Trace: (SUM '2 '13)
5. Trace: (SUM '1 '14)
6. Trace: (SUM '0 '15)
6. Trace: SUM ==> 15
5. Trace: SUM ==> 15
4. Trace: SUM ==> 15
3. Trace: SUM ==> 15
2. Trace: SUM ==> 15
1. Trace: SUM ==> 15
15 ;;;The result
使用另一种方法可以找到同样的结果,我不明白,但似乎更常见:
> (defun sum (n1 n2) "Return the sum of two nonnegative numbers."
(if (zerop n1) n2 (1+ (sum2 (1- n1) n2))))
> (sum 5 10)
1. Trace: (SUM '5 '10)
2. Trace: (SUM '4 '10)
3. Trace: (SUM '3 '10)
4. Trace: (SUM '2 '10)
5. Trace: (SUM '1 '10)
6. Trace: (SUM '0 '10)
6. Trace: SUM ==> 10
5. Trace: SUM ==> 11
4. Trace: SUM ==> 12
3. Trace: SUM ==> 13
2. Trace: SUM ==> 14
1. Trace: SUM ==> 15
15
可以清楚地看到,这些非常不同并获得相同的结果。 lisp如何允许第二种方法中的行为,以及函数+1
在第二种方法中通过向函数添加1来执行什么操作,因为函数不是变量?
我从 "COMMON LISP: An Interactive Approach"
答案 0 :(得分:1)
sum2
并不是那么不同。两者都来自n1
;第一个sum
将其移至n2
,而第二个将其添加到递归调用的结果中。
关于第一个sum
的好处是它是尾递归:它只返回递归调用的结果,可以更有效地实现(并且更紧密地实现)模拟一个循环)。