You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Common Lisp中用cons替换append实现列表及子列表反转?

如何用cons替换append实现递归反转列表及子列表?

你用append实现的revert能正确递归反转列表及所有子列表,但直接替换成cons后会产生多层嵌套结构,这是因为append和cons的行为本质不同:

  • append是将两个列表的元素扁平拼接,比如(append '(a b) '(c))会得到(a b c);
  • cons是将第一个参数作为单个元素加到第二个参数的头部,比如(cons '(a b) '(c))会得到((a b) c),这就是你看到嵌套结构的核心原因。

要想用cons实现原函数的效果,核心是模拟append将单个元素追加到列表末尾的行为——原逻辑中append的第二个参数始终是(list (revert (car l)))(单元素列表),因此我们只需要用cons递归完成“元素追加到列表末尾”的操作即可。

解决方案1:使用辅助函数

先定义一个用cons实现的追加函数,再替换原函数中的append:

;; 用cons实现:将元素elem追加到列表lst的末尾
(defun append-elem-to-end (lst elem)
  (if (null lst)
      (list elem)  ;; 列表为空时,直接返回包含elem的列表
      (cons (car lst)  ;; 否则递归处理cdr,把elem追加到后面
            (append-elem-to-end (cdr lst) elem))))

;; 改造后的revert函数
(defun revert (l)
  (cond
    ((atom l) l)
    (t (append-elem-to-end (revert (cdr l))  ;; 替换原append的位置
                           (revert (car l))))))

测试验证:

(write (revert '(2 3 5 6 7 8 9 (4 5 (6)))))
;; 输出:(((6) 5 4) 9 8 7 6 5 3 2),与原函数结果一致

解决方案2:内联辅助逻辑(无额外函数)

如果不想定义辅助函数,可以直接把追加逻辑内联到revert中:

(defun revert (l)
  (cond
    ((atom l) l)
    ((null (cdr l))  ;; 列表只剩一个元素时,返回反转后的单元素列表
     (list (revert (car l))))
    (t  ;; 递归处理cdr,将当前car的反转结果追加到cdr反转结果的末尾
     (cons (car (revert (cdr l)))
           (revert (cons (cdr (cdr l)) (list (car l))))))))

这个版本的核心是:每次递归时,先取(revert (cdr l))的第一个元素作为当前cons的car,再递归处理剩余的(cdr (cdr l))与当前car组成的新列表,最终实现将当前car的反转结果追加到末尾的效果。

原替换方式失效的原因

你直接把append换成cons后,代码变为:

(cons (revert (cdr l)) (list (revert (car l))))

这里(revert (cdr l))是一个完整列表,cons会把它当成单个元素放到新列表头部,而非展开元素进行拼接,因此每次递归都会新增一层嵌套,最终得到全嵌套的异常结果。

内容的提问来源于stack exchange,提问作者Leo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:35:17