X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Flist.lisp;h=36adc0e9f4b647a870e951f7d4598a346dcc0d70;hb=0105d7b5712cbfd3b0bf8e527f562071b3c12151;hp=f7e15ec064b0db9a905431a0ab9e2acec99ad09b;hpb=3c567e1c9acaa34cde1ca0df46f34895301b89d8;p=jscl.git diff --git a/src/list.lisp b/src/list.lisp index f7e15ec..36adc0e 100644 --- a/src/list.lisp +++ b/src/list.lisp @@ -13,9 +13,11 @@ ;; You should have received a copy of the GNU General Public License ;; along with JSCL. If not, see . +(/debug "loading list.lisp!") + ;;;; Various list functions -(defun cons (x y ) (cons x y)) +(defun cons (x y) (cons x y)) (defun consp (x) (consp x)) (defun listp (x) @@ -68,6 +70,16 @@ (defun nth (n list) (car (nthcdr n list))) +(define-setf-expander nth (n list) + (let ((g!list (gensym)) + (g!index (gensym)) + (g!value (gensym))) + (values (list g!list g!index) + (list list n) + (list g!value) + `(rplaca (nthcdr ,g!index ,g!list) ,g!value) + `(nth ,g!index ,g!list)))) + (defun caar (x) (car (car x))) (defun cadr (x) (car (cdr x))) (defun cdar (x) (cdr (car x))) @@ -114,14 +126,17 @@ (s tree))) (defun subst (new old tree &key key (test #'eql testp) (test-not #'eql test-not-p)) - (when (and testp test-not-p) - (error "Both test and test-not are set")) (labels ((s (x) - (let ((key-val (if key (funcall key x) x))) - (cond - ((funcall (if test-not-p test-not test) key-val old) new) - ((atom x) x) - (t (cons (s (car x)) (s (cdr x)))))))) + (cond ((satisfies-test-p old x :key key :test test :testp testp + :test-not test-not :test-not-p test-not-p) + new) + ((atom x) x) + (t (let ((a (s (car x))) + (b (s (cdr x)))) + (if (and (eq a (car x)) + (eq b (cdr x))) + x + (cons a b))))))) (s tree))) (defun copy-list (x) @@ -133,12 +148,17 @@ (copy-tree (cdr tree))) tree)) -(defun tree-equal (tree1 tree2 &key (test #'eql)) - (if (atom tree1) - (and (atom tree2) (funcall test tree1 tree2)) - (and (consp tree2) - (tree-equal (car tree1) (car tree2) :test test) - (tree-equal (cdr tree1) (cdr tree2) :test test)))) +(defun tree-equal (tree1 tree2 &key (test #'eql testp) + (test-not #'eql test-not-p)) + (when (and testp test-not-p) (error "Both test and test-not are set")) + (let ((func (if test-not-p (complement test-not) test))) + (labels ((%tree-equal (tree1 tree2) + (if (atom tree1) + (and (atom tree2) (funcall func tree1 tree2)) + (and (consp tree2) + (%tree-equal (car tree1) (car tree2)) + (%tree-equal (cdr tree1) (cdr tree2)))))) + (%tree-equal tree1 tree2)))) (defun tailp (object list) (do ((tail list (cdr tail))) @@ -176,10 +196,29 @@ (rplaca tail (cdar tail))) (collect (apply func elems)))))))) +(defun mapn (func list) + (with-collect + (while list + (collect (funcall func list)) + (setq list (cdr list))))) + +(defun maplist (func list &rest lists) + (let ((lists (cons list lists))) + (with-collect + (block loop + (loop + (let ((elems (mapn #'car lists))) + (do ((tail lists (cdr tail))) + ((null tail)) + (when (null (car tail)) (return-from loop)) + (rplaca tail (cdar tail))) + (collect (apply func elems)))))))) + (defun mapc (func &rest lists) - (do* ((elems (map1 #'car lists) (map1 #'car lists-rest)) - (lists-rest (map1 #'cdr lists) (map1 #'cdr lists-rest))) - ((dolist (x elems) (when (null x) (return t))) + (do* ((tails lists (map1 #'cdr tails)) + (elems (map1 #'car tails) + (map1 #'car tails))) + ((dolist (x tails) (when (null x) (return t))) (car lists)) (apply func elems))) @@ -192,23 +231,27 @@ (and (consp (cdr x)) (cons (car x) (butlast (cdr x))))) -(defun member (x list &key (key #'identity) (test #'eql)) +(defun member (x list &key key (test #'eql testp) (test-not #'eql test-not-p)) (while list - (when (funcall test x (funcall key (car list))) + (when (satisfies-test-p x (car list) :key key :test test :testp testp + :test-not test-not :test-not-p test-not-p) (return list)) (setq list (cdr list)))) -(defun assoc (x alist &key (test #'eql)) +(defun assoc (x alist &key key (test #'eql testp) (test-not #'eql test-not-p)) (while alist - (if (funcall test x (caar alist)) + (if (satisfies-test-p x (caar alist) :key key :test test :testp testp + :test-not test-not :test-not-p test-not-p) (return) (setq alist (cdr alist)))) (car alist)) -(defun rassoc (x alist &key (test #'eql)) +(defun rassoc (x alist &key key (test #'eql) (test #'eql testp) + (test-not #'eql test-not-p)) (while alist - (if (funcall test x (cdar alist)) + (if (satisfies-test-p x (cdar alist) :key key :test test :testp testp + :test-not test-not :test-not-p test-not-p) (return) (setq alist (cdr alist)))) (car alist)) @@ -247,7 +290,7 @@ (list x) (list new-value) `(progn (rplacd ,cons ,new-value) ,new-value) - `(car ,cons)))) + `(cdr ,cons)))) ;; The NCONC function is based on the SBCL's one. @@ -295,6 +338,6 @@ (defun intersection (list1 list2 &key (test #'eql) (key #'identity)) (let ((new-list ())) (dolist (x list1) - (when (member x list2 :test test :key key) + (when (member (funcall key x) list2 :test test :key key) (push x new-list))) new-list))