Zach Beane xach@xach.com writes:
"James M. Lawrence" llmjjmll@gmail.com writes:
Using two loops seems awkward to me. How about one?
(defun delete-from-plist (plist &rest keys) (loop with head = plist with tail = nil for (key . rest) on plist by #'cddr do (assert rest () "Expected a proper plist, got ~S" plist) (if (member key keys :test #'eq) (let ((next (cdr rest))) (if tail (setf (cdr tail) next) (setf head next))) (setf tail rest)) finally (return head)))
I mention this for completeness and novelty, not for suitability:
(defun sans (plist &rest keys) (let ((sans ())) (loop (let ((tail (nth-value 2 (get-properties plist keys)))) ;; this is how it ends (unless tail (return (nreconc sans plist))) ;; copy all the unmatched keys (loop until (eq plist tail) do (push (pop plist) sans) (push (pop plist) sans)) ;; skip the matched key (setq plist (cddr plist))))))
I don't think I've seen GET-PROPERTIES and NRECONC outside this function.
I got it from here: http://xach.com/naggum/articles/3247672165664225%40naggum.no.html
If striving for shortness:
(defun delete-from-plist (plist &rest keys) (dolist (key keys plist) (remf plist key)))