From: Jeff Dalton
Subject: REMOVE may not copy; pitfalls list
Date: 
Message-ID: <6163@skye.ed.ac.uk>
In article <······················@arris.com> ········@arris.com (Richard Shapiro) writes:

>Yes, yes. And on page 399 it says REMOVE returns a *copy* of its
>sequence argument. I think we've established that the 399 description
>is more than a little misleading.

I suppose that anything that misleads someone is indeed misleading.
But page 399 isn't the only place that will be misleading if you read
only part of the specification of a function, and it's hard to
describe REMOVE without saying something that's at least somewhat
misleading if you read only part of the description.

Perhaps there's room for a "pitfalls" list, on things that people
may not expect Common Lisp to do and that will be revealed only on
caseful reading.  Some things I'd put in are:

  1. The result REMOVE can share structure with the argument.
     (As can a number of other functions, such as UNION.)

  2. Destructive functions that you think would modify CDRs might
     modify CARs instead.  (Eg, NREVERSE.)

  3. SORT is (usually) destructive.

So, for instance,  (SORT (REMOVE ...) ...)  may not be safe.

  4. You often have to declare the result type to get the most
     efficient arithmetic.  Eg, 

       (the fixnum (+ (the fixnum e1) (the fixnum e2)))

     rather than

       (+ (the fixnum e1) (the fixnum e2))

  5. Array elements might not be initialized to NIL.  Eg,

       (make-array 10) => #(0 0 0 0 0 0 0 0 0 0)

  6. The array-total-size-limit may be as small as 1024.

  7. Such things as (apply #'append list-of-lists) to flatten a list
     of lists may run afoul of call-arguments-limit.

     Alternatives include:

       (reduce #'append list-of-lists :from-end t)

       (mapcan #'copy-list list-of-lists)

-- jd