CLISP - 扭转一个简单的列表

时间:2012-04-19 02:41:02

标签: lisp common-lisp clisp

我必须反转简单(单维)列表的元素。我知道这里有一个内置的反向功能,但我无法使用它。

这是我的尝试:

(defun LISTREVERSE (LISTR)
    (cond
        ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
        (t (cons (LISTREVERSE (cdr LISTR)) (car LISTR))) ; move first to the end
    )
)

输出非常接近,但是错了。

[88]> (LISTREVERSE '(0 1 2 3)) 
((((3) . 2) . 1) . 0)

所以我尝试使用append代替cons

(t (append (LISTREVERSE (cdr LISTR)) (car LISTR)))

但得到了这个错误:

*** - APPEND: A proper list must not end with 2

任何帮助?

4 个答案:

答案 0 :(得分:6)

我可以给你一些指示,因为这看起来像是作业:

  • 当列表为空(null)时递归的基本情况,当列表中的元素少于两个时
  • 考虑使用额外参数定义辅助函数,在空列表中初始化“累加器”。对于原始列表中的每个元素,cons位于累加器的头部。当输入列表为空时,返回累加器

另外,上面的解决方案是尾递归的。

答案 1 :(得分:3)

作为ÓscarLópez的后续行动(并试图只是写下不同的解决方案):

  • 同时使用appendlength会使发布的解决方案成为逆转列表效率最低的方法。查看有关consnull的文档,了解有关如何实施此问题的更多建议。
  • indent properly
  • 在这种情况下,尾递归确实更有效且相当简单。如果你还没有尝试的话。 labels是您要用于定义本地递归函数的表单。
  • 翻阅The Little Schemer可能值得您花些时间。它会让你更好地感受一般的递归。

答案 2 :(得分:0)

你做的很好。您只错过了结果列表的组成。

考虑一下:你必须将CAR的1元素列表附加到反转CDR列表的末尾:

(defun LISTREVERSE (LISTR)
    (cons
        ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
        (t (append (LISTREVERSE (cdr LISTR)) (list (car  LISTR))))))

答案 3 :(得分:0)

(defun listreverse (list)
  (let (result)
    (dolist (item list result)
      (push item result))))
  • 当有一种简单的迭代方式来达到相同的目标时,不要在Common Lisp中使用递归。 Common Lisp对尾递归没有任何保证,并且你的尾递归函数调用可能不会根据编译器的判断优化为跳转。
  • push将该项目添加到结果
  • dolist有一个可选的第三个参数,它是返回的值。退出循环时会对其进行评估。