X-Git-Url: http://git.kpe.io/?p=kmrcl.git;a=blobdiff_plain;f=lists.lisp;h=5cd193cefe96910174ef1c9a9a5039c0b1c9b7b5;hp=35e74ba3482236cf8dd4f01cfc6948de66e273bd;hb=5a1ba26220b15f493fac354c0e411c1f2f57d20d;hpb=eb3a19183eef0273cb4bec74259f98802fb141f0 diff --git a/lists.lisp b/lists.lisp index 35e74ba..5cd193c 100644 --- a/lists.lisp +++ b/lists.lisp @@ -42,90 +42,94 @@ (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)) + (list car-strip)) ((and car-strip cdr-strip) - (cons car-strip cdr-strip)) + (cons car-strip cdr-strip)) (car-strip - car-strip) + car-strip) (cdr-strip - cdr-strip))))) + cdr-strip))))) (defun find-tree (sym tree) "Finds an atom as a car in tree and returns cdr tree at that positions" (if (or (null tree) (atom tree)) nil (if (eql sym (car tree)) - (cdr tree) + (cdr tree) (aif (find-tree sym (car tree)) - it - (aif (find-tree sym (cdr tree)) - it - nil))))) + it + (aif (find-tree sym (cdr tree)) + it + nil))))) (defun flatten (lis) (cond ((atom lis) lis) - ((listp (car lis)) - (append (flatten (car lis)) (flatten (cdr lis)))) - (t (append (list (car lis)) (flatten (cdr lis)))))) + ((listp (car lis)) + (append (flatten (car lis)) (flatten (cdr lis)))) + (t (append (list (car lis)) (flatten (cdr lis)))))) ;;; Keyword functions +;; ECL doesn't allow FOR clauses after UNTIL. +#-ecl (defun remove-keyword (key arglist) (loop for sublist = arglist then rest until (null sublist) - for (elt arg . rest) = sublist - unless (eq key elt) append (list elt arg))) + for (elt arg . rest) = sublist + unless (eq key elt) append (list elt arg))) (defun remove-keywords (key-names args) (loop for ( name val ) on args by #'cddr - unless (member (symbol-name name) key-names - :key #'symbol-name :test 'equal) - append (list name val))) + unless (member (symbol-name name) key-names + :key #'symbol-name :test 'equal) + append (list name val))) (defun mapappend (func seq) (apply #'append (mapcar func seq))) (defun mapcar-append-string-nontailrec (func v) - "Concatenate results of mapcar lambda calls" + "Concatenate results of mapcar lambda calls" (aif (car v) (concatenate 'string (funcall func it) - (mapcar-append-string-nontailrec func (cdr v))) + (mapcar-append-string-nontailrec func (cdr v))) "")) (defun mapcar-append-string (func v &optional (accum "")) - "Concatenate results of mapcar lambda calls" + "Concatenate results of mapcar lambda calls" (aif (car v) - (mapcar-append-string - func - (cdr v) - (concatenate 'string accum (funcall func it))) + (mapcar-append-string + func + (cdr v) + (concatenate 'string accum (funcall func it))) accum)) (defun mapcar2-append-string-nontailrec (func la lb) - "Concatenate results of mapcar lambda call's over two lists" + "Concatenate results of mapcar lambda call's over two lists" (let ((a (car la)) - (b (car lb))) + (b (car lb))) (if (and a b) (concatenate 'string (funcall func a b) - (mapcar2-append-string-nontailrec func (cdr la) (cdr lb))) + (mapcar2-append-string-nontailrec func (cdr la) (cdr lb))) ""))) - + (defun mapcar2-append-string (func la lb &optional (accum "")) - "Concatenate results of mapcar lambda call's over two lists" + "Concatenate results of mapcar lambda call's over two lists" (let ((a (car la)) - (b (car lb))) + (b (car lb))) (if (and a b) - (mapcar2-append-string func (cdr la) (cdr lb) - (concatenate 'string accum (funcall func a b))) + (mapcar2-append-string func (cdr la) (cdr lb) + (concatenate 'string accum (funcall func a b))) accum))) (defun append-sublists (list) @@ -149,18 +153,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) @@ -178,9 +188,18 @@ (let ((pos (gensym))) `(let ((,pos (member ,pkey ,plist :test ,test))) (if ,pos - (progn - (setf (cadr ,pos) ,value) - ,plist) - (setf ,plist (append ,plist (list ,pkey ,value))))))) + (progn + (setf (cadr ,pos) ,value) + ,plist) + (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)))))) +