0.9.3.13:
authorPaul F. Dietz <pfdietz@users.sourceforge.net>
Mon, 1 Aug 2005 04:23:41 +0000 (04:23 +0000)
committerPaul F. Dietz <pfdietz@users.sourceforge.net>
Mon, 1 Aug 2005 04:23:41 +0000 (04:23 +0000)
 -- Make list-remove-duplicates use a hash table only if the number
    of items to traverse is more than 20.
 -- Add special case routine LAST1 (equivalent to single argument
   call to LAST) and have NCONC call this instead of the general
   function.
 -- Add a special two-argument form of NCONC, called NCONC2. TODO:
    add a source transform to call this.

src/code/list.lisp
src/code/seq.lisp
src/compiler/fndb.lisp
version.lisp-expr

index e21535c..b328681 100644 (file)
@@ -18,8 +18,8 @@
 ;;;; -- WHN 20000127
 
 (declaim (maybe-inline
-          tree-equal nth %setnth nthcdr last make-list append
-          nconc member member-if member-if-not tailp adjoin union
+          tree-equal nth %setnth nthcdr last last1 make-list append
+          nconc nconc2 member member-if member-if-not tailp adjoin union
           nunion intersection nintersection set-difference nset-difference
           set-exclusive-or nset-exclusive-or subsetp acons assoc
           assoc-if assoc-if-not rassoc rassoc-if rassoc-if-not subst subst-if
               (fast-nthcdr (mod n i) r-i))
            (declare (type index i)))))))
 
+(defun last1 (list)
+  #!+sb-doc
+  "Return the last cons (not the last element) of a list"
+  (let ((rest list))
+    (loop (unless (consp rest) (return list))
+          (shiftf list rest (cdr rest)))))
+
 (defun last (list &optional (n 1))
   #!+sb-doc
   "Return the last N conses (not the last element!) of a list."
-  (if (typep n 'index)
-      (do ((checked-list list (cdr checked-list))
-           (returned-list list)
-           (index 0 (1+ index)))
-          ((atom checked-list) returned-list)
-        (declare (type index index))
-        (if (>= index n)
-            (pop returned-list)))
-      list))
+  (if (eql n 1)
+      (last1 list)
+    (if (typep n 'index)
+        (do ((checked-list list (cdr checked-list))
+             (returned-list list)
+             (index 0 (1+ index)))
+            ((atom checked-list) returned-list)
+          (declare (type index index))
+          (if (>= index n)
+              (pop returned-list)))
+      list)))
 
 (defun list (&rest args)
   #!+sb-doc
                  ((endp elements))
                (let ((ele (car elements)))
                  (typecase ele
-                   (cons (rplacd (last splice) ele)
+                   (cons (rplacd (last1 splice) ele)
                          (setf splice ele))
-                   (null (rplacd (last splice) nil))
+                   (null (rplacd (last1 splice) nil))
                    (atom (if (cdr elements)
                              (fail ele)
-                             (rplacd (last splice) ele)))
+                             (rplacd (last1 splice) ele)))
                    (t (fail ele)))))
              (return result)))
           (null)
                (return top-of-top)))
           (t (fail top-of-top)))))))
 
+(defun nconc2 (x y)
+  (if (null x) y
+    (let ((z x)
+          (rest (cdr x)))
+      (loop
+       (unless (consp rest)
+         (rplacd z y)
+         (return x))
+       (shiftf z rest (cdr rest))))))
+
 (defun nreconc (x y)
   #!+sb-doc
   "Return (NCONC (NREVERSE X) Y)."
           (setf (car l) (cdar l)))
         (setq res (apply fun (nreverse args)))
         (case accumulate
-          (:nconc (setq temp (last (nconc temp res))))
+          (:nconc (setq temp (last1 (nconc temp res))))
           (:list (rplacd temp (list res))
                  (setq temp (cdr temp))))))))
 
index 67ade1b..5fe1f97 100644 (file)
          (splice result)
          (current list)
          (end (or end (length list)))
-         (hash (and test
+         (hash (and (> (- end start) 20)
+                    test
                     (not key)
                     (not test-not)
                     (or (eql test #'eql)
                         (eql test #'eq)
                         (eql test #'equal)
                         (eql test #'equalp))
-                    ; (> (- end start) 20)
                     (make-hash-table :test test :size (- end start)))))
     (do ((index 0 (1+ index)))
         ((= index start))
index 704e7f0..49f9cfe 100644 (file)
 (defknown nth (unsigned-byte list) t (foldable flushable))
 (defknown nthcdr (unsigned-byte list) t (foldable unsafely-flushable))
 (defknown last (list &optional unsigned-byte) t (foldable flushable))
+(defknown sb!impl::last1 (list) t (foldable flushable))
 (defknown list (&rest t) list (movable flushable unsafe))
 (defknown list* (t &rest t) t (movable flushable unsafe))
 (defknown make-list (index &key (:initial-element t)) list
 ;;; express that in this syntax. The result must be LIST, but we do
 ;;; not check it now :-).
 (defknown nconc (&rest t) t ())
+(defknown sb!impl::nconc2 (list t) t ())
 
 (defknown nreconc (list t) t ())
 (defknown butlast (list &optional unsigned-byte) list (flushable))
index da52f48..7f3b8d1 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.3.12"
+"0.9.3.13"