eql5-sfos/lisp/software/alexandria-20210807-git/alexandria-2/lists.lisp
2021-12-10 22:02:34 +01:00

24 lines
944 B
Common Lisp

(in-package :alexandria-2)
(defun delete-from-plist* (plist &rest keys)
"Just like REMOVE-FROM-PLIST, but this version may destructively modify the
provided PLIST.
The second return value is an alist of the removed items, in unspecified order."
;; TODO: a plist?
(declare (optimize speed))
(loop with head = plist
with tail = nil ; a nil tail means an empty result so far
with kept = ()
for (key . rest) on plist by #'cddr
do (assert rest () "Expected a proper plist, got ~S" plist)
(if (member key keys :test #'eq)
;; skip over this pair
(let ((next (cdr rest)))
(push (cons key (car rest))
kept)
(if tail
(setf (cdr tail) next)
(setf head next)))
;; keep this pair
(setf tail rest))
finally (return (values head kept))))