Re: How to make a copy of a list



På Wed, 30 Apr 2008 00:59:58 +0200, skrev Kaz Kylheku <kkylheku@xxxxxxxxx>:

On Apr 29, 2:54 pm, "John Thingstad" <jpth...@xxxxxxxxx> wrote:
(defun deep-copy-sequence (sequence)
   "Recursivly copy all array's and list's."
   (cond
    ((arrayp sequence)
(setf sequence (copy-seq sequence))

ARRAYP matches multidimensional arrays, which are not sequences and
cannot be passed to COPY-SEQ. But it wouldn't be hard to add support
for copying them.

     (loop for element across sequence
           when (subtypep (type-of element) 'sequence)
           do (setf element (deep-copy-sequence element))))
    ((listp sequence)

Since all your COND tests are for type, TYPECASE can be used instead:

(typecase sequence
(vector ...)
(list ...)
...
(otherwise ...))


     (setf sequence (copy-list sequence))
     (loop for element in sequence
           when (subtypep (type-of element) 'sequence)
           do (setf element (deep-copy-sequence element)))))
   sequence)

The problem here is that although the semantics of COPY-TREE are
extended here to cover vector structure as well as cons structure,
nothing is done about atoms at all; they are not replicated.

(defgeneric deep-copy (whatever))

(defmethod deep-copy ((vec vector))
(map 'vector #'deep-copy vec))

(defmethod deep-copy ((cons cons))
(cons (deep-copy (car cons))
(deep-copy (cdr cons))))


UGH. this is not scheme.

;; Note: this is what handles (deep-copy nil) -> nil,
;; if there is no specialization to NULL, since NIL
;; is a kind of symbol.
(defmethod deep-copy ((sym symbol)) sym)

(defmethod deep-copy ((num number)) num)

Now we can add multi-dimensional array support. CLOS should match on
VECTOR more specifically if the array is one dimensional, and pass the
greater than rank 2 ones to this specialization:

(defmethod deep-copy ((array array))
;; exercise for reader
)

We don't have a T specialization, so DEEP-COPY will blow up with a no
applicable method error if it doesn't know how to copy something. E.g.

(deep-copy *random-state*)

For this one, we can just write

(defmethod deep-copy ((rs random-state))
(make-random-state rs))

Etc.




Too complicated..
Indeed inspect uses a approach like you described.
I figure my simple algorithm (the first) covers most cases where you would want do do this. If it is too slow you should probably find a alternative to copying anyway. The same is the case if it contains classes and the like. It is better to let the classes themselves provide a copying scheme. Let context rule whether shallow-copy deep-copy or structural-copy is desirable. deep-copy is too blunt and general. If it's need arises it might be a sign that your design is wrong.

--------------
John Thingstad
.



Relevant Pages

  • Re: How to make a copy of a list
    ...     ... (setf sequence (copy-seq sequence)) ... (defmethod deep-copy ((vec vector)) ... Now we can add multi-dimensional array support. ...
    (comp.lang.lisp)
  • Re: Choice sequence lessons.
    ... and that their right is just as good as the orthodox mathie. ... a whole system of *generating* a sequence. ... interpretations of things - the difference ... vs     NOT ANY of the students will pass. ...
    (sci.logic)
  • Re: The complete infinite binary tree has only countably many infinite paths, says WM.
    ...   That is not what you must do. ... Denote the leading node of any sequence of nodes by its number followed ... In that infinite tree, ...
    (sci.logic)
  • Re: Did I deserve this zero?
    ... Concentrated values in the black suits, comfortable rebid, two unstopped ... Given this sequence,  yes, you deserve the bottom. ... hand and trying to figure out how to bid this hand, ...   Instead you chose a bid that absolutely ...
    (rec.games.bridge)
  • Re: Reinventing the iterator
    ... RST returns the rest of the sequence (lazily) ... The main purpose of SEQ is to give the ability to iterate over various ... just use lists (it's the most simple and ...   "The analog of DOLIST for any collection COLL, ...
    (comp.lang.lisp)