POSITION-IF, POSITION-IF-NOT (except :FROM-END)
authorKen Harris <kengruven@gmail.com>
Thu, 13 Jun 2013 06:07:23 +0000 (23:07 -0700)
committerKen Harris <kengruven@gmail.com>
Thu, 13 Jun 2013 06:07:23 +0000 (23:07 -0700)
src/sequence.lisp
tests/seq.lisp

index 981f559..7f86a85 100644 (file)
                                    :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
     ((null seq)
index c39b0ce..ce1c8d6 100644 (file)
 (test (= (position 1 #(1 1 3) :test-not #'=) 2))
 (test (= (position 1 '(1 1 3) :test-not #'=) 2))
 
+;; POSITION-IF, POSITION-IF-NOT
+(test (= 2 (position-if #'oddp '((1) (2) (3) (4)) :start 1 :key #'car)))
+(test (= 4 (position-if-not #'integerp '(1 2 3 4 X))))  ;; (hyperspec example used "5.0", but we don't have a full numeric tower yet!)
+
 ; REMOVE-IF
 (test (equal (remove-if     #'zerop '(1 0 2 0 3)) '(1 2 3)))
 (test (equal (remove-if-not #'zerop '(1 0 2 0 3)) '(0 0)))