【问题标题】:Is it possible to limit the number of calls to the cons function in the duplicate() function?是否可以在 duplicate() 函数中限制对 cons 函数的调用次数?
【发布时间】: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


【解决方案1】:

不,出于同样的原因,你不能用 5 升水装满一个 10 升的桶。

10 个元素的列表需要 10 个 cons 单元格。

【讨论】:

  • 感谢您的帮助。您的 cmets 证实了我的观点
【解决方案2】:

破坏性版本可以做到这一点:

(defun duplicate (l)
  (if (null l)
      nil
    (destructuring-bind (f . r)
        l
      (setf (cdr l)
            (cons f (duplicate r)))
      l)))

CL-USER 10 > (duplicate (list 1 2 3 4 5))
(1 1 2 2 3 3 4 4 5 5)

【讨论】:

    【解决方案3】:

    你可以消除所有的缺点:

    (list* (car l) (car l) (duplicate (cdr l)))

    【讨论】:

    • 你怎么能确定 list* 不会在任何 Common Lisp 实现中调用 cons
    • 在某种程度上我很搞笑,但我也认为 OP 可能正在寻找一种方法来避免 coding 两个 cons 调用,因此提供了更好的 list* 语法.但回想起来,我看到trace 被视为真相的来源,所以我的水晶球可能让我失望了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多