;;;; Programmer: Kevin M. Rosenberg
;;;; Date Started: Apr 2000
;;;;
-;;;; $Id: lists.lisp,v 1.4 2003/05/11 21:51:43 kevin Exp $
+;;;; $Id: lists.lisp,v 1.9 2003/07/31 07:32:11 kevin Exp $
;;;;
;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;;
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************
-(in-package :kmrcl)
-
+(in-package #:kmrcl)
(defun mklist (obj)
"Make into list if atom"
(if (listp obj) obj (list obj)))
+(defun map-and-remove-nils (fn lst)
+ "mao a list by function, eliminate elements where fn returns nil"
+ (let ((acc nil))
+ (dolist (x lst (nreverse acc))
+ (let ((val (funcall fn x)))
+ (when val (push val acc))))))
+
(defun filter (fn lst)
"Filter a list by function, eliminate elements where fn returns nil"
(let ((acc nil))
(dolist (x lst (nreverse acc))
- (let ((val (funcall fn x)))
- (if val (push val acc))))))
+ (when (funcall fn x)
+ (push x acc)))))
(defun appendnew (l1 l2)
"Append two lists, filtering out elem from second list that are already in first list"
(dolist (elem (cdr list) results)
(setq results (append results elem)))))
+
+;; alists and plists
+
+(defun alist-elem-p (elem)
+ (and (consp elem) (atom (car elem)) (atom (cdr elem))))
+
+(defun alistp (alist)
+ (when (listp alist)
+ (dolist (elem alist)
+ (unless (alist-elem-p elem)
+ (return-from alistp nil)))
+ t))
+
+(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))))))
+
+(defun get-alist (key alist &key (test #'eql))
+ (cdr (assoc key alist :test test)))
+
+(defun (setf get-alist) (value key alist &key (test #'eql))
+ (update-alist key value alist :test test)
+ value)
+
+(defun alist-plist (alist)
+ (apply #'append (mapcar #'(lambda (x) (list (car x) (cdr x))) alist)))
+
+(defun plist-alist (plist)
+ (do ((alist '())
+ (pl plist (cddr plist)))
+ ((null pl) alist)
+ (setq alist (acons (car pl) (cadr pl) alist))))
+
+(defmacro update-plist (pkey value plist &key (test '#'eql))
+ "Macro to support below (setf get-alist)"
+ (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)))))))
+
+