From c65b589ccfc3aec5971287b05d94e7882706efa2 Mon Sep 17 00:00:00 2001 From: Owen Rodley Date: Thu, 9 May 2013 14:51:33 +1200 Subject: [PATCH] Implement REMOVE-IF[-NOT] for vectors --- src/sequence.lisp | 46 +++++++++++++++++++++++++++------------------- tests/seq.lisp | 8 ++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/sequence.lisp b/src/sequence.lisp index 93e3fdd..738995f 100644 --- a/src/sequence.lisp +++ b/src/sequence.lisp @@ -92,30 +92,38 @@ (return-from every nil))) t) - -;;; TODO: Support both List and vectors in the following functions - -(defun remove-if (func list) +(defun remove-if (func seq) (cond - ((null list) - nil) - ((funcall func (car list)) - (remove-if func (cdr list))) - (t - ;; - (cons (car list) (remove-if func (cdr list)))))) + ((listp seq) (list-remove-if func seq nil)) + ((arrayp seq) (vector-remove-if func seq nil)) + (t (error "`~S' is not of type SEQUENCE" seq)))) -(defun remove-if-not (func list) +(defun remove-if-not (func seq) (cond - ((null list) - nil) - ((funcall func (car list)) - (cons (car list) (remove-if-not func (cdr list)))) - (t - (remove-if-not func (cdr list))))) + ((listp seq) (list-remove-if func seq t)) + ((arrayp seq) (vector-remove-if func seq t)) + (t (error "`~S' is not of type SEQUENCE" seq)))) + +(defun list-remove-if (func list negate) + (if (endp list) + () + (let ((test (funcall func (car list)))) + (if (if negate (not test) test) + (list-remove-if func (cdr list) negate) + (cons (car list) (list-remove-if func (cdr list) negate)))))) + +(defun vector-remove-if (func vector negate) + (let ((out-vector (make-array 0))) + (dotimes (i (length vector)) + (let* ((element (aref vector i)) + (test (funcall func element))) + (when (if negate test (not test)) + (vector-push-extend element out-vector)))) + out-vector)) + +;;; TODO: Support both List and vectors in the following functions (defun subseq (seq a &optional b) (if b (slice seq a b) (slice seq a))) - diff --git a/tests/seq.lisp b/tests/seq.lisp index 326b4f7..c117831 100644 --- a/tests/seq.lisp +++ b/tests/seq.lisp @@ -5,3 +5,11 @@ (test (find 1 (list 2 1 3))) (test (not (find 1 (list 2 2 2)))) (test (not (find 1 (remove 1 (list 1 2 3 1))))) + +(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))) + +;; TODO: Rewrite these tests when EQUALP exists and works on vectors +(let ((v1 (remove-if #'zerop #(1 0 2 0 3)))) + (test (and (= (aref v1 0) 1) (= (aref v1 1) 2) (= (aref v1 2) 3)))) +(test (every #'zerop (remove-if-not #'zerop #(1 0 2 0 3)))) -- 1.7.10.4