+(defun replace-all (string part replacement &key (test #'char=) stream)
+ "Returns a new string in which all the occurences of the part
+is replaced with replacement. [FROM http://cl-cookbook.sourceforge.net/strings.html#manip]"
+ (let ((out (or stream (make-string-output-stream))))
+ (loop with part-length = (length part)
+ for old-pos = 0 then (+ pos part-length)
+ for pos = (search part string
+ :start2 old-pos
+ :test test)
+ do (write-string string out
+ :start old-pos
+ :end (or pos (length string)))
+ when pos do (write-string replacement out)
+ while pos)
+ (unless stream
+ (get-output-stream-string out))))
+
+
+(defun filter-plist (plist &rest keys-to-remove)
+ "Returns a copy of the given plist with indicated key-value pairs
+removed. keys are searched with #'MEMBER"
+ (declare (dynamic-extent keys-to-remove))
+ (when plist
+ (loop for (k v . rest) = plist then rest
+ unless (member k keys-to-remove)
+ collect k and collect v
+ while rest)))