【问题标题】:Just trying to recursively print a list, nothing prints though只是试图递归打印一个列表,但什么也没打印
【发布时间】:2011-06-27 14:05:24
【问题描述】:

我想浏览一个列表(可能有嵌套列表)并让它评估为一个包含所有元素的扁平列表。我什至无法得到一个递归函数来评估nil以外的任何东西

(defun pl(lst)
  (if (atom lst)
      lst
    (progn
      (pl (car lst))
      (pl (cdr lst)))))

然后我会用(pl '(1 (2 3) (4 5))) 之类的东西打电话,但它总是评估为nil

我变了

(if (atom lst) lst

(if (atom lst) (print lst)

这甚至不会打印列表中的任何项目。

我在这里缺少什么概念?

【问题讨论】:

  • 您是否确定在进行更改后重新加载了defun?我认为更改为(print lst) 应该可以解决问题...

标签: list recursion printing lisp


【解决方案1】:

一个函数通常只会返回一个值,即它的函数体的值。如果您仔细查看pl,您会发现它是一个if 表单,因此pl 要么返回lst 的值,要么返回progn 的值。

这里首先要指出的是(progn ...) 表单的返回值是它最后一个表达式的值,在这种情况下是递归调用(pl (cdr lst))。由于您没有对(pl (car lst)) 的返回值执行任何操作,因此此调用没有任何效果。递归调用的值将在某个时候通过atom 测试。这里要指出的第二件事是(atom nil) 也是如此。请记住,列表的最后一个元素是 nil,所以当您给 pl 一个列表时,它会总是返回 nil,正如您所观察到的。

如果您的打印版本没有显示任何内容,可能是因为打印输出显示在其他地方,例如在另一个缓冲区中。

至于解决方案:您要么想要一个纯递归解决方案,使用append 而不是progn,因为这是您的家庭作业。在常规 lisp 中,您只需使用其中一种迭代结构。

我的建议是查看任何有关 lisp 或方案的教科书,以掌握递归和尾递归的基础知识。

【讨论】:

    【解决方案2】:

    您可以考虑查看介绍性文字,例如“The Little Schemer”。它所做的第一件事就是向您展示如何对这样的问题采取一致的方法。生成的函数可能如下所示:

    (define (pl lst)
      (cond ((null? lst) '())
            ((not (pair? lst)) (list lst))
            (else (append (pl (car lst))
                          (pl (cdr lst))))))
    

    当然,这是 Scheme,但 Lisp 的方法是一样的:

    • 检查参数为 nil 的特殊情况
    • 检查参数是原子的特殊情况
    • 递归地将函数应用于参数的 car 和 cdr,并附加结果

    Lisp 中的相同函数如下所示:

    (defun pl (lst)
       (cond ((null lst) '())
             ((atom lst) (list lst))
             (t (append (pl (car lst))
                        (pl (cdr lst))))))
    

    可以说这不是最有效的代码,但这不是重点。这种类型的模式一遍又一遍地出现。这是一个很好的习语。

    【讨论】:

      猜你喜欢
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      • 2016-06-12
      • 1970-01-01
      • 2020-01-04
      • 2016-05-07
      • 1970-01-01
      相关资源
      最近更新 更多