--- /dev/null
+(in-package :lisp-on-lines)
+
+
+
+
+;;;; PLIST Utilities.
+
+(defun plist-nunion (new-props plist)
+ "Destructive Merge of plists. PLIST is modified and returned.
+NEW-PROPS is merged into PLIST such that any properties
+in both PLIST and NEW-PROPS get the value in NEW-PROPS.
+The other properties in PLIST are left untouched."
+ (loop for cons on new-props by #'cddr
+ do (setf (getf plist (first cons)) (second cons))
+ finally (return plist))
+ plist)
+
+(defun plist-union (new-props plist)
+ "Non-destructive version of plist-nunion"
+ (plist-nunion new-props (copy-list plist)))
+
+
+
+
+
+
+(defun slots-as-properties (object)
+ "Makes a plist by making a keyword from the ...ahh .. read the damn code"
+ (mapcan
+ #'(lambda (slot-name)
+ (when (slot-boundp object slot-name)
+
+ (list (intern (symbol-name slot-name)
+ (find-package :keyword))
+ (slot-value object slot-name))))
+ (list-slots object)))
+
+(defun properties-as-slots (plist)
+ "takes a plist and turns it into slot-definitions, interning the key names in *package*"
+ (loop for (key val) on plist by #'cddr
+ collect (let ((name (intern (symbol-name key))))
+ `(,name :accessor ,name :initarg ,key :special t :initform ,val))))
+
+(defmacro with-properties ((properties &optional (prefix '||)) &body body)
+ (with-unique-names (p)
+ (let ((get (intern (strcat prefix '.get)))
+ (set (intern (strcat prefix '.set)))
+ (props (intern (strcat prefix '.properties))))
+ `(let ((,p ,properties))
+ (flet ((,get (p)
+ (getf ,p p))
+ (,set (p v)
+ (setf (getf ,p p) v))
+ (,props ()
+ ,p))
+ (declare (ignorable #',get #',set #',props))
+ ,@body)))))
\ No newline at end of file