CLISP-反转简单列表

CLISP-反转简单列表,lisp,common-lisp,clisp,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 ) )

我必须反转一个简单(单一维度)列表中的元素。我知道有一个内置的反转功能,但我不能用它来做这个

以下是我的尝试:

(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
    )
)
因此,我尝试使用
append
而不是
cons

(t (append (LISTREVERSE (cdr LISTR)) (car LISTR)))
但我犯了这个错误:

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

有什么帮助吗?

我可以给你一些建议,因为这看起来像是家庭作业:

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

作为旁白,上述解决方案是尾部递归的。

作为Óscar López的后续行动(与写下不同解决方案的诱惑作斗争):

  • 同时使用
    append
    length
    使发布的解决方案几乎成为反转列表的最低效方法。查看文档,了解如何实现这一点的一些更好的想法
  • 求你了,求你了
  • 在这种情况下,尾部递归实际上更有效,也更简单。如果你还没有试过的话,试试看。是要用于定义局部递归函数的表单
  • 这可能值得你翻阅一下。一般来说,它会让您对递归有更好的感觉

    • 你所做的一切都没关系。你只是错过了结果表的组成部分

      考虑一下:您必须将汽车的1元素列表附加到反向CDR列表的末尾:

      (defun LISTREVERSE (LISTR)
          (cons
              ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
              (t (append (LISTREVERSE (cdr LISTR)) (list (car  LISTR))))))
      
      (取消列表反转(LISTR)
      (缺点
      ((<(长度列表)2)列表;列表为1个原子或更小
      (t(附加(列表反向(cdr列表))(列表(汽车列表()())))
      
      • 当有一种简单的迭代方法可以达到相同的目标时,不要在CommonLisp中使用递归。Common Lisp不保证尾部递归,编译器可能不会自行决定是否将尾部递归函数调用优化为跳转
      • push
        将项目添加到结果前
      • dolist
        有一个可选的第三个参数,它是返回的值。在退出循环时对其进行计算

      我尝试使用基本大小写null来执行此操作,但随后得到
      (((NIL 3)2)1)0)
      。另外,我知道lisp中需要尾部递归才能快速运行,但我不想在规范中说“一个函数”时过度使用它。@user1342836您得到这些奇怪的结果正是因为您没有使用参数作为累加器来保存结果。在这种情况下,最简单的解决方案恰好也是有效的:使用累加器-顺便说一句,这是一个尾部递归,你不会“过度”它。我让它在没有尾部递归的情况下工作,但只是因为它是一个单一维度列表(我可以看到需要更多维度)。不过null是基本情况。谢谢你hint@user1342836伟大的很抱歉,我不能给你一个直截了当的回答,做人们的家庭作业是违反网站政策的。不管怎样,如果这个答案对你有帮助,请考虑接受它(点击左边的检查标记),使用长度不是一个好主意。它违背了链接单元格列表的目的。长度遍历整个列表以确定长度。追加错误有点神秘,但这意味着最后一个参数不是列表,而是数字2。除非我弄错了,否则只要将最后一个参数放入列表中,
      APPEND
      版本就可以工作。那些缩进规则很愚蠢+1,对于其他部分的回答。@ SethCARNGEGE-我推断你是一个C++或java程序员,编辑器不做括号匹配。在那个页面上的缩进系统后面是LISP编程世界的绝大部分。我怀疑您只看了第一个示例,没有看到上面的句子“不要这样写:”。普通的Lisp编译器不需要支持尾部递归。这是Lisp中的优化,而不是Scheme中的语义需求。
      (defun LISTREVERSE (LISTR)
          (cons
              ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
              (t (append (LISTREVERSE (cdr LISTR)) (list (car  LISTR))))))
      
      (defun listreverse (list)
        (let (result)
          (dolist (item list result)
            (push item result))))