Elisp深度复制 - 消费

时间:2013-06-02 19:02:43

标签: elisp

我正在尝试在elisp中实现我自己的深层复制例程(因为像(setq newlist oldlist)这样的东西似乎只提供了一个浅层副本,(copy-sequence newlist oldlist)仍然让newlist暴露给任何oldlist

元素的变化

此外,如果有一个功能可以实现我想要的功能,那我就找不到运气了。

我的功能定义是:

(defun deep-copy (iList oList)

    (setq oList (car iList))
    (setq counter (- (length iList) 1))
    (setq iList (cdr iList))
    (while (> counter 0)
        (setq oList (cons oList (car iList)))
        (setq iList (cdr iList))
        (setq counter (- counter 1) )))

之后,iList的{​​{1}} (1 2 3 4 5 6)恰好有oList(((((1 . 2) . 3) . 4) . 5) . 6) 即嵌套列表。

我尝试引用,引用,使用追加,在oList中切换(car iList)(cons # #)的顺序,谷歌搜索解决方案,但我没有运气(或者错误或垃圾)。

除了对已经存在的功能已经存在的任何欢迎评论,如果代码中存在弱点(我是elisp新手),有什么功能可以告诉我如何正确地将元素包含在现有列表中?

示例往往是表单的变体:(cons 'pine '(fir oak maple)),其中'(fir oak maple)是一些硬编码列表

编辑:在过去的两个小时里,我一直在与自己作斗争(因为我在调用函数中注释掉了oList,并且我一直在引用它的旧版本)。无论如何,交换oList(car iList)然后在最后反转似乎可以解决问题(但肯定有更好的方法!?),即

(defun deep-copy (iList)
  (setq oList nil )
  (setq counter (- (length iList) 1))
  (while (>= counter 0)
    (setq oList (cons (car iList) oList) )
    (setq iList (cdr iList) )
    (setq counter (- counter 1) ))
  (reverse oList)
    )

2 个答案:

答案 0 :(得分:8)

使用copy-tree(示例假设您为require d cl,为方便起见,copy-tree本身不需要它:

elisp> (setq list1 '(((1 2) (3 4)) 5 (6)))
(((1 2)
  (3 4))
 5
 (6))

elisp> (setq list2 (copy-sequence list1))
(((1 2)
  (3 4))
 5
 (6))

elisp> (setf (caar list2) 1)
1
elisp> list2
((1
  (3 4))
 5
 (6))

elisp> list1
((1
  (3 4))
 5
 (6))

elisp> (setq list1 '(((1 2) (3 4)) 5 (6)))
(((1 2)
  (3 4))
 5
 (6))

elisp> (setq list2 (copy-tree list1))
(((1 2)
  (3 4))
 5
 (6))

elisp> (setf (caar list2) 1)
1
elisp> list1
(((1 2)
  (3 4))
 5
 (6))

elisp> list2
((1
  (3 4))
 5
 (6))

我建议您阅读Emacs附带的Elisp简介:C-h i g (eintr) RET或其他介绍性的Lisp书籍,例如Touretzky(后者适用于Common Lisp),而不是提供有关代码的提示。 ,但很棒的介绍)。它将教你基础知识 - 例如,不只是函数定义中的setq等。

但是举个例子,这里是copy-tree的定义(或者,只需在你的Emacs中查看它:M-x find-function RET copy-tree RET):

(defun copy-tree (tree &optional vecp)
  "Make a copy of TREE.
If TREE is a cons cell, this recursively copies both its car and its cdr.
Contrast to `copy-sequence', which copies only along the cdrs.  With second
argument VECP, this copies vectors as well as conses."
  (if (consp tree)
      (let (result)
    (while (consp tree)
      (let ((newcar (car tree)))
        (if (or (consp (car tree)) (and vecp (vectorp (car tree))))
        (setq newcar (copy-tree (car tree) vecp)))
        (push newcar result))
      (setq tree (cdr tree)))
    (nconc (nreverse result) tree))
    (if (and vecp (vectorp tree))
    (let ((i (length (setq tree (copy-sequence tree)))))
      (while (>= (setq i (1- i)) 0)
        (aset tree i (copy-tree (aref tree i) vecp)))
      tree)
      tree)))

答案 1 :(得分:7)

Elisp的功能为copy-tree。它是copy-sequence的递归版本:

示例

(let* ((orig '((1 2) (3 4)))
       (copy (copy-tree orig)))
  (setcdr (cadr copy) '(0))
  (list orig copy))
==> (((1 2) (3 4)) ((1 2) (3 0)))

在你的情况下你可以写:

(setq oList (copy-tree iList))