[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: remove



haltraet@monsun.si.no (Hallvard Tr{tteberg) writes:
  Hi, I'm profiling some code and found out that it's consing much more
  than it should. I found that the following is true of MCL 2.0:
 
   (let ((a '(1 2 3))) (eq    a (remove 0 a))) => nil, while of course
   (let ((a '(1 2 3))) (equal a (remove 0 a))) => t
 
   Remove conses up a new list even though it doesn't remove anything!

Hallvard Traetteberg then goes on to define a "smart" remove.
 
Guy Steele Jr, in Common Lisp the Language (second edition)
makes the following comment about the remove, remove-if, and remove-if-not
sequence modifiers:
 
"The result is a sequence of the same kind as the argument sequence
that has the same elements except that those in the subsequence delimited
by :start and :end and satisfying the test have been removed.  This is
a non-destructive operation; the result is a copy of the input sequence,
save that some elements are not copied."

If you want to minimize the consing and you don't mind modifying
the original list, use the destructive counterpart of remove
(nremove 0 a). This won't cons.

? (time 
   (let ((list '(a b c d))
         (element 0))
     (dotimes (i 1000)
       (setq list (remove element list)))))
      
(LET ((LIST '(A B C D)) (ELEMENT 0)) (DOTIMES (I 1000) (SETQ LIST (REMOVE ELEMENT LIST)))) 
took 1455 milliseconds (1.455 seconds) to run.
Of that, 91 milliseconds (0.091 seconds) were spent in The Cooperative Multitasking Experience.
737 milliseconds (0.737 seconds) was spent in GC.
 32000 bytes of memory allocated.
NIL
? (time 
   (let ((list '(a b c d))
         (element 0))
     (dotimes (i 1000)
       (setq list (nremove element list)))))
(LET ((LIST '(A B C D)) (ELEMENT 0)) (DOTIMES (I 1000) (SETQ LIST (NREMOVE ELEMENT LIST)))) 
took 68 milliseconds (0.068 seconds) to run.
Of that, 1 milliseconds (0.001 seconds) were spent in The Cooperative Multitasking Experience.
NIL
?