Re: How to make a copy of a list
- From: "John Thingstad" <jpthing@xxxxxxxxx>
- Date: Wed, 30 Apr 2008 07:48:10 +0200
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
.
- References:
- How to make a copy of a list
- From: Trastabuga
- Re: How to make a copy of a list
- From: John Thingstad
- Re: How to make a copy of a list
- From: John Thingstad
- Re: How to make a copy of a list
- From: John Thingstad
- Re: How to make a copy of a list
- From: Kaz Kylheku
- How to make a copy of a list
- Prev by Date: Re: How to make a copy of a list
- Next by Date: Re: How to make a copy of a list
- Previous by thread: Re: How to make a copy of a list
- Next by thread: Re: How to make a copy of a list
- Index(es):
Relevant Pages
|