From: Richard Lynch
Subject: Re: Hey, I thought REMOVE was supposed to be non-destructive!
Date: 
Message-ID: <lynch-2807941722430001@lynch.ils.nwu.edu>
In article <····················@hume.cs.orst.edu>,
······@hume.cs.orst.edu (Peter Dudey) wrote:

|CLtL2 (p. 399) says remove and it's relatives are non-destructive.  Is
|this proper behavior, then?
|
|> (setq foo '(a b c d))
|(A B C D)
|> (setq bar (remove 'a foo))
|(B C D)
|> (delete 'd bar)
|(B C)
|> foo
|(A B C)
|>

Yes.

In general non-destructive means only that the original sequence is
intact.  It does not mean that what you get back is a whole fresh
sequence.  Page 399 *does* say 'the result is a copy of the input
sequence', but this is really meant to be read as an explanation of
intent, rather than implementation.  Page 400 clearly states:  'The result
of remove may share with the argument sequence; a list result may share a
tail with an input list, and the result may be eq to the input sequence if
no elements need to be removed'.  This is true for all the non-destructive
sequences.  To guarantee that you are not sharing structure, you have to
use copy-list/copy-tree.

The destruction comes about from your use of delete [which I assume you
know *is* destructive.]

Note also that delete is *allowed* to be destructive; it is not required
to be.  Thus, it is entirely legal [though sub-optimal] for delete to
simply call remove, and you *CANNOT* count on the side-effects of delete
to have modified your data structure.  In your example, bar *could*
legally still be (B C D), though it most likely is (B C).  If you had done
(delete 'b bar), bar would almost certainly still be (B C D).

Hmmm, if the forthcoming spec still reads 'the result is a copy of the
input sequence', perhaps this could be reworded and/or the info about
shared structure could be physically closer to it.

-- 
-- 
--
-- "TANSTAAFL"  Rich ·····@ils.nwu.edu