【发布时间】:2017-03-10 14:04:58
【问题描述】:
我编写了函数double() 复制列表中的项目,如下所示:
(defun duplicate (l)
(if (null l) nil
(cons (car l) (cons (car l) ( duplicate (cdr l))))))
duplicate() 函数为列表中的每个项目调用 CONS 函数两次:
Break 1 [2]> (trace cons)
;; Traçage de la fonction CONS.
(CONS)
Break 1 [2]> ( duplicate '(1 2 3))
1. Trace: (CONS '3 'NIL)
1. Trace: CONS ==> (3)
1. Trace: (CONS '3 '(3))
1. Trace: CONS ==> (3 3)
1. Trace: (CONS '2 '(3 3))
1. Trace: CONS ==> (2 3 3)
1. Trace: (CONS '2 '(2 3 3))
1. Trace: CONS ==> (2 2 3 3)
1. Trace: (CONS '1 '(2 2 3 3))
1. Trace: CONS ==> (1 2 2 3 3)
1. Trace: (CONS '1 '(1 2 2 3 3))
1. Trace: CONS ==> (1 1 2 2 3 3)
(1 1 2 2 3 3)
是否可以将CONS 函数的调用次数限制为每个列表项一次?
【问题讨论】:
-
最终,不,因为
cons只向列表添加一项,而您在每一步添加两项。 -
我们不能将
cons函数与lisp 映射函数结合起来解决这个问题吗? -
我认为这取决于您的实现是否对连接两个列表进行了优化。从概念上讲(我认为),任何构建新列表的方法都是通过将一个元素一次添加到任意长列表的前面来实现的。
-
如果您愿意破坏性地修改旧列表,当然可以。但思考这一点的关键是要意识到 cons 是列表中的一个节点。对于具有 2n 个节点的列表,您需要 2n 个 cons 单元。如果您真的担心对 CONS 函数的显式调用,请改用 LIST*:
(list* (car l) (car l) (duplicate (cdr l)))。
标签: list duplicates lisp common-lisp cons