Lisp递归混乱

时间:2014-11-17 01:47:46

标签: recursion lisp common-lisp tail-recursion

我相信这是独立的实现,但我在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"

的第15章获得了这两个函数

1 个答案:

答案 0 :(得分:1)

sum2并不是那么不同。两者都来自n1;第一个sum将其移至n2,而第二个将其添加到递归调用的结果中。

关于第一个sum的好处是它是尾递归:它只返回递归调用的结果,可以更有效地实现(并且更紧密地实现)模拟一个循环)。