Remove CODE completely
[jscl.git] / src / sequence.lisp
index 6ac3ebf..be36e99 100644 (file)
@@ -13,6 +13,8 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with JSCL.  If not, see <http://www.gnu.org/licenses/>.
 
+(/debug "loading sequence.lisp!")
+
 (defun not-seq-error (thing)
   (error "`~S' is not of type SEQUENCE" thing))
 
         (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.
      (if b
        (let ((diff (- b a)))
          (cond
-           ((zerop  diff) ()) 
+           ((zerop  diff) ())
            ((minusp diff)
             (error "Start index must be smaller than end index"))
            (t
                 (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))))
-    ((arrayp seq) 
-     (if b
-       (slice seq a b)
-       (slice seq a)))
+    ((vectorp seq)
+     (let* ((b (or b (length seq)))
+            (size (- b a))
+            (new (make-array size :element-type (array-element-type seq))))
+       (do ((i 0 (1+ i))
+            (j a (1+ j)))
+           ((= 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))))))