recursion - Lisp 中的递归函数如何工作?

标签 recursion lisp common-lisp

所以我用 Lisp 编码,并想出了一个计算列表中原子数量的函数(没有子列表)。所以代码是这样的:

(defun num-atoms (list)
  (cond
    ((null list) 0)
    ((atom list) 1)
    (t (+ (num-atoms (car list))
          (num-atoms (cdr list))))))

这对我来说有效并且有意义。因此,如果我在参数中使用列表 (1 2 3) 调用此函数,它应该如下所示:

  • (原子数'(1 2 3))
  • 不为空
  • 不是原子
  • 原子数(1)
  • 原子所以返回 1
  • 原子数 ((2 3))
  • 不为空
  • 不是原子
  • 原子数 (2)
  • 返回1
  • ...
  • 等等

但是,如果我这样编写代码:

(defun num-atoms (list)
  (cond
    ((null list) 0)
    ((atom list) 1)
    (t (+ (num-atoms (cdr list))
          (num-atoms (car list))))))

这里我只是在最后一行交换了 de car 和 cdr 的位置。

它仍然有效!如果我进行跟踪,它会给出相同顺序的原子数量!它首先计算 '(1 2 3) 列表中的 1,依此类推。 有人可以向我解释一下第二个版本的代码仍然如何工作吗?我不太明白这里的逻辑。

最佳答案

如果您trace您将看到这两个功能有何不同。

在您的第一个版本中,原子按顺序处理,因为该函数处理第一个元素 (car),然后处理其余元素 (cdr)。

在第二个版本中,原子以相反的顺序进行处理,因为函数在处理第一个元素之前首先处理剩余的元素。因此找到的第一个原子是列表中的最后一个原子,然后堆栈展开。

当然,两种情况的结果是相同的,因为加法是 commutative .

* (defun num-atoms(list)
  (cond
   ((null list) 0)
   ((atom list) 1)
   (t (+ (num-atoms (car list)) (num-atoms (cdr list))))))

NUM-ATOMS
* (trace num-atoms)

(NUM-ATOMS)
* (num-atoms '(1 2 3))
  0: (NUM-ATOMS (1 2 3))
    1: (NUM-ATOMS 1)
    1: NUM-ATOMS returned 1
    1: (NUM-ATOMS (2 3))
      2: (NUM-ATOMS 2)
      2: NUM-ATOMS returned 1
      2: (NUM-ATOMS (3))
        3: (NUM-ATOMS 3)
        3: NUM-ATOMS returned 1
        3: (NUM-ATOMS NIL)
        3: NUM-ATOMS returned 0
      2: NUM-ATOMS returned 1
    1: NUM-ATOMS returned 2
  0: NUM-ATOMS returned 3
3

* (defun num-atoms(list)
  (cond
   ((null list) 0)
   ((atom list) 1)
   (t (+ (num-atoms (cdr list)) (num-atoms (car list))))))

NUM-ATOMS
* (num-atoms '(1 2 3))
  0: (NUM-ATOMS (1 2 3))
    1: (NUM-ATOMS (2 3))
      2: (NUM-ATOMS (3))
        3: (NUM-ATOMS NIL)
        3: NUM-ATOMS returned 0
        3: (NUM-ATOMS 3)
        3: NUM-ATOMS returned 1
      2: NUM-ATOMS returned 1
      2: (NUM-ATOMS 2)
      2: NUM-ATOMS returned 1
    1: NUM-ATOMS returned 2
    1: (NUM-ATOMS 1)
    1: NUM-ATOMS returned 1
  0: NUM-ATOMS returned 3
3
*

关于recursion - Lisp 中的递归函数如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33462610/

相关文章:

swift - 如何使用 codable 和 swift 递归解析 json

java - 汉诺塔代码中的错误

javascript - 如何阻止递归函数修改它自己的变量?

lisp - Peter Norvig 的人工智能编程范式中的练习 1.2

scheme - 非空 Scheme 列表是否包含至少一个原子?

lisp - 传教士和食人者 - LISP

lisp - 这个函数不应该返回包含其中所有元素的列表吗?

count - 在 L. LISP 的任何地方发现符号 A 的出现

java - 我可以从递归返回到 main 而不展开堆栈吗?

emacs - 修改 emacs 自动填充功能的工作方式