X-Git-Url: http://git.kpe.io/?p=kmrcl.git;a=blobdiff_plain;f=lists.lisp;h=dfa9d386d25d5c9f100c317372442b3ef15adcff;hp=35e74ba3482236cf8dd4f01cfc6948de66e273bd;hb=ea921dd2ce51a46bb3ca92a07df095d5ace99dcf;hpb=eb3a19183eef0273cb4bec74259f98802fb141f0 diff --git a/lists.lisp b/lists.lisp index 35e74ba..dfa9d38 100644 --- a/lists.lisp +++ b/lists.lisp @@ -42,13 +42,15 @@ (unless (find elem l1) (setq l1 (append l1 (list elem)))))) -(defun remove-from-tree-if (pred tree) +(defun remove-from-tree-if (pred tree &optional atom-processor) "Strip from tree of atoms that satistify predicate" (if (atom tree) (unless (funcall pred tree) - tree) - (let ((car-strip (remove-from-tree-if pred (car tree))) - (cdr-strip (remove-from-tree-if pred (cdr tree)))) + (if atom-processor + (funcall atom-processor tree) + tree)) + (let ((car-strip (remove-from-tree-if pred (car tree) atom-processor)) + (cdr-strip (remove-from-tree-if pred (cdr tree) atom-processor))) (cond ((and car-strip (atom (cadr tree)) (null cdr-strip)) (list car-strip)) @@ -149,18 +151,24 @@ (defmacro update-alist (akey value alist &key (test '#'eql) (key '#'identity)) "Macro to support below (setf get-alist)" - (let ((elem (gensym))) - `(let ((,elem (assoc ,akey ,alist :test ,test :key ,key))) - (if ,elem - (progn - (setf (cdr ,elem) ,value) - ,alist) - (setf ,alist (acons ,akey ,value ,alist)))))) + (let ((elem (gensym "ELEM-")) + (val (gensym "VAL-"))) + `(let ((,elem (assoc ,akey ,alist :test ,test :key ,key)) + (,val ,value)) + (cond + (,elem + (setf (cdr ,elem) ,val)) + (,alist + (setf (cdr (last ,alist)) (list (cons ,akey ,val)))) + (t + (setf ,alist (list (cons ,akey ,val))))) + ,alist))) (defun get-alist (key alist &key (test #'eql)) (cdr (assoc key alist :test test))) (defun (setf get-alist) (value key alist &key (test #'eql)) + "This won't work if the alist is NIL." (update-alist key value alist :test test) value) @@ -184,3 +192,12 @@ (setf ,plist (append ,plist (list ,pkey ,value))))))) +(defun unique-slot-values (list slot &key (test 'eql)) + (let ((uniq '())) + (dolist (item list (nreverse uniq)) + (let ((value (slot-value item slot))) + (unless (find value uniq :test test) + (push value uniq)))))) + + +