Recursion Lisp中的递归加法

Recursion Lisp中的递归加法,recursion,lisp,common-lisp,addition,Recursion,Lisp,Common Lisp,Addition,我是一个初学者,我正在努力自学公共Lisp,在我的自学过程中,我编写了一个函数,我认为该函数适用于两个参数的递归加法。但是,该功能总是失败。为什么呢 (defun sum (n m) ;;;Returns the sum of n and m using recursion (cond ((eq m 0) n)) (sum (1+ n) (1- m))) 据我所知,它应该不断地向n添加1,同时递减m,直到m为0,在这一点上,递归加法是完整的进行这种加法确实是一个非常好的用例,但我将

我是一个初学者,我正在努力自学公共Lisp,在我的自学过程中,我编写了一个函数,我认为该函数适用于两个参数的递归加法。但是,该功能总是失败。为什么呢

(defun sum (n m)
  ;;;Returns the sum of n and m using recursion
  (cond ((eq m 0) n))
  (sum (1+ n) (1- m)))

据我所知,它应该不断地向n添加1,同时递减m,直到m为0,在这一点上,递归加法是完整的

进行这种加法确实是一个非常好的用例,但我将向您解释您的错误在哪里:

(defun sum (n m)
  ;;;Returns the sum of n and m using recursion
  (cond ((eq m 0) n)) ;; <= This line is ignored, you not returnin N.
  (sum (1+ n) (1- m))) ;; <= this will be called forever
让我们跟踪它,看看它是如何工作的:

CL-USER> (sum 0 10) 
  0: (SUM 0 10)
    1: (SUM 1 9)
      2: (SUM 2 8)
        3: (SUM 3 7)
          4: (SUM 4 6)
            5: (SUM 5 5)
              6: (SUM 6 4)
                7: (SUM 7 3)
                  8: (SUM 8 2)
                    9: (SUM 9 1)
                      10: (SUM 10 0)
                      10: SUM returned 10
                    9: SUM returned 10
                  8: SUM returned 10
                7: SUM returned 10
              6: SUM returned 10
            5: SUM returned 10
          4: SUM returned 10
        3: SUM returned 10
      2: SUM returned 10
    1: SUM returned 10
  0: SUM returned 10
10

如果您愿意接受建议,请不要尝试使用递归做这种奇怪的事情,如果您想学习如何使用它,请尝试将其用于一些自然的递归情况,如阶乘、斐波那契、树处理等。

我想您有两个简单的输入错误:

  • 一个括号太多,太多
  • 您的
    cond
    子句中缺少
    t
    你的意思可能是:

    (defun sum (n m)
      (cond 
       ((eq m 0) n)               ; here you had one parenthesis too many
       (t (sum (1+ n) (1- m)))))  ; here you were missing the `t` symbol
    

    您可以递归调用
    SUM
    。当堆栈溢出时,它停止。也许你应该改善一下状况,让它停止自鸣。。。如果,请尝试使用
    。另外,
    EQ
    不适用于数字。使用
    EQL
    =
    。根据代码,缩进是正确的
    cond
    做一些被丢弃的事情(
    n
    nil
    ),然后通过添加
    n
    和减少
    m
    无条件递归。它不会返回
    nil
    ,因为它不会停止。你收到堆栈溢出消息了吗?@Sylvester是的,我在Emacs中收到堆栈溢出消息。研究其他人对我的纠正向我展示了我是如何把cond语句搞砸的,以及为什么递归永远不会结束。或者至少让
    cond
    测试表单彼此对齐。如果cond与对sum的递归调用不在同一级别,则很容易发现错误。当然,他可以使用cond,但是如果只有两个分支,if是惯用的。是的,显然if在这里更惯用。只要提到cond,以防OP在其他情况下遇到类似的问题,cond将是惯用的。谢谢。我认为我对Lisp的理解要好得多,并且可以看出我的代码失败的原因。我当然会接受你的建议,坚持更自然的递归问题:)OP的用例是一个标准的教科书示例,在大学的可计算性课程中使用递归来建立原始操作。谢谢。我原以为我的代码完全错了,但看到我还有两个小的打字错误,这有点令人鼓舞。@BurnedOut不,你差得太近了。虽然我在这里也会使用
    if
    而不是
    cond
    ,但有些人出于各种原因建议始终使用
    cond
    ,例如。
    (defun sum (n m)
      (cond 
       ((eq m 0) n)               ; here you had one parenthesis too many
       (t (sum (1+ n) (1- m)))))  ; here you were missing the `t` symbol