X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fsequence.lisp;h=be36e994fedeef7904f48a9c61b48c6b91dcb71f;hb=fc17cd58e6bd60aa129bb879e3cf7452a944384b;hp=7e96df080b88b646e0e2b6823713b1686ffa487b;hpb=5dafe038d2ba676341b824c55e3f6bad16411c1a;p=jscl.git diff --git a/src/sequence.lisp b/src/sequence.lisp index 7e96df0..be36e99 100644 --- a/src/sequence.lisp +++ b/src/sequence.lisp @@ -13,6 +13,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with JSCL. If not, see . +(/debug "loading sequence.lisp!") + (defun not-seq-error (thing) (error "`~S' is not of type SEQUENCE" thing)) @@ -48,12 +50,36 @@ (when (funcall predicate x) (return x))))) -(defun position (elt sequence &key key (test #'eql testp) - (test-not #'eql test-not-p)) - (do-sequence (x sequence index) - (when (satisfies-test-p elt x :key key :test test :testp testp - :test-not test-not :test-not-p test-not-p ) - (return index)))) +(defun position (elt sequence + &key key (test #'eql testp) + (test-not #'eql test-not-p) + (start 0) end) + ;; TODO: Implement START and END efficiently for all the sequence + ;; functions. + (let ((end (or end (length sequence)))) + (do-sequence (x sequence index) + (when (and (<= start index) + (< index end) + (satisfies-test-p elt x + :key key :test test :testp testp + :test-not test-not :test-not-p test-not-p)) + (return index))))) + +;; TODO: need to support &key from-end +(defun position-if (predicate sequence + &key key (start 0) end) + ;; TODO: Implement START and END efficiently for all the sequence + ;; functions. + (let ((end (or end (length sequence)))) + (do-sequence (x sequence index) + (when (and (<= start index) + (< index end) + (funcall predicate (if key (funcall key x) x))) + (return index))))) + +(defun position-if-not (predicate sequence + &key key (start 0) end) + (position-if (complement predicate) sequence :key key :start start :end end)) (defun remove (x seq &key key (test #'eql testp) (test-not #'eql test-not-p)) (cond @@ -63,7 +89,7 @@ (let* ((head (cons nil nil)) (tail head)) (do-sequence (elt seq) - (unless (satisfies-test-p x elt :key key :test test :testp testp + (unless (satisfies-test-p x elt :key key :test test :testp testp :test-not test-not :test-not-p test-not-p) (let ((new (list elt))) (rplacd tail new) @@ -72,7 +98,7 @@ (t (let (vector) (do-sequence (elt seq index) - (if (satisfies-test-p x elt :key key :test test :testp testp + (if (satisfies-test-p x elt :key key :test test :testp testp :test-not test-not :test-not-p test-not-p) ;; Copy the beginning of the vector only when we find an element ;; that does not match. @@ -130,7 +156,7 @@ (if b (let ((diff (- b a))) (cond - ((zerop diff) ()) + ((zerop diff) ()) ((minusp diff) (error "Start index must be smaller than end index")) (t @@ -140,7 +166,7 @@ (setq pointer (cdr pointer)) (when (null pointer) (error "Ending index larger than length of list"))) - (rplacd pointer ()) + (rplacd pointer ()) drop-a)))) (copy-list (nthcdr a seq)))) ((vectorp seq) @@ -152,3 +178,32 @@ ((= j b) new) (aset new i (aref seq j))))) (t (not-seq-error seq)))) + +(defun copy-seq (sequence) + (subseq sequence 0)) + + +;;; Reduce (based on SBCL's version) + +(defun reduce (function sequence &key key from-end (start 0) end (initial-value nil ivp)) + (let ((key (or key #'identity)) + (end (or end (length sequence)))) + (if (= end start) + (if ivp initial-value (funcall function)) + (macrolet ((reduce-list (function sequence key start end initial-value ivp from-end) + `(let ((sequence + ,(if from-end + `(reverse (nthcdr ,start ,sequence)) + `(nthcdr ,start ,sequence)))) + (do ((count (if ,ivp ,start (1+ ,start)) + (1+ count)) + (sequence (if ,ivp sequence (cdr sequence)) + (cdr sequence)) + (value (if ,ivp ,initial-value (funcall ,key (car sequence))) + ,(if from-end + `(funcall ,function (funcall ,key (car sequence)) value) + `(funcall ,function value (funcall ,key (car sequence)))))) + ((>= count ,end) value))))) + (if from-end + (reduce-list function sequence key start end initial-value ivp t) + (reduce-list function sequence key start end initial-value ivp nil))))))