-- 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.
;;;; -- WHN 20000127
(declaim (maybe-inline
;;;; -- 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
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)))))))
(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."
(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
(defun list (&rest args)
#!+sb-doc
((endp elements))
(let ((ele (car elements)))
(typecase ele
((endp elements))
(let ((ele (car elements)))
(typecase ele
- (cons (rplacd (last splice) ele)
+ (cons (rplacd (last1 splice) ele)
- (null (rplacd (last splice) nil))
+ (null (rplacd (last1 splice) nil))
(atom (if (cdr elements)
(fail ele)
(atom (if (cdr elements)
(fail ele)
- (rplacd (last splice) ele)))
+ (rplacd (last1 splice) ele)))
(t (fail ele)))))
(return result)))
(null)
(t (fail ele)))))
(return result)))
(null)
(return top-of-top)))
(t (fail top-of-top)))))))
(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)."
(defun nreconc (x y)
#!+sb-doc
"Return (NCONC (NREVERSE X) Y)."
(setf (car l) (cdar l)))
(setq res (apply fun (nreverse args)))
(case accumulate
(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))))))))
(:list (rplacd temp (list res))
(setq temp (cdr temp))))))))
(splice result)
(current list)
(end (or end (length list)))
(splice result)
(current list)
(end (or end (length list)))
+ (hash (and (> (- end start) 20)
+ test
(not key)
(not test-not)
(or (eql test #'eql)
(eql test #'eq)
(eql test #'equal)
(eql test #'equalp))
(not key)
(not test-not)
(or (eql test #'eql)
(eql test #'eq)
(eql test #'equal)
(eql test #'equalp))
(make-hash-table :test test :size (- end start)))))
(do ((index 0 (1+ index)))
((= index start))
(make-hash-table :test test :size (- end start)))))
(do ((index 0 (1+ index)))
((= index start))
(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 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
(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 ())
;;; 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))
(defknown nreconc (list t) t ())
(defknown butlast (list &optional unsigned-byte) list (flushable))
;;; 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".)
;;; 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".)