[alexandria-devel] Implementation of DELETE-FROM-PLIST
Robert Smith
quad at symbo1ics.com
Sat Feb 23 09:15:18 UTC 2013
Attached is a proper patch.
-Robert
On Sat, Feb 23, 2013 at 1:09 AM, Robert Smith <quad at symbo1ics.com> wrote:
> Hey:
>
> Here's a destructive/non-consing version of DELETE-FROM-PLIST. I've
> tested with (I think) all corner cases from the REPL, but I ought to
> write tests proper.
>
> The function is here http://tinyurl.com/adqkssu ;or the following huge
> link, in case the last one is invalidated
> https://bitbucket.org/tarballs_are_good/lisp-random/src/3db634111d35e788c6ea2f4a1b3ab38334e24cde/miscellaneous_exercises/delete-from-plist.lisp?at=default#cl-30
> .
>
> For simplicity or ease of review from an email client, I've pasted the
> function at the end of this email.
>
> Additionally, this function would make it pretty easy to write
> DELETE-FROM-PLIST-IF{-NOT}, since the function to determine if a key
> is bad is factored out. If one did write this function, then it would
> be easy to define DELETE-FROM-PLIST in terms of it.
>
> Let me know if there are any changes that should be made.
>
> Cheers,
>
> Robert Smith
>
>
> ;;;; from delete-from-plist.lisp
>
> (defun delete-from-plist (plist &rest keys)
> "Delete all keys and pairs indicated by KEYS from the plist PLIST."
> (labels ((assert-proper-plist (x)
> (assert x () "Expected a proper plist, got ~S" plist))
> (bad-key-p (key)
> (member key keys :test #'eq))
> (find-first ()
> "Find the first cons in PLIST to keep."
> (loop :for the-cons :on plist :by #'cddr
> :unless (prog1 (bad-key-p (car the-cons))
> (assert-proper-plist (cdr the-cons)))
> :do (return the-cons)
> :finally (return nil))))
> (declare (inline assert-proper-plist
> bad-key-p
> find-first))
> ;; Find the first good key and delete any bad key-value pairs
> ;; between it and the start.
> (let ((first (find-first)))
> (unless (eq first plist)
> (setf (cddr plist)
> first))
>
> ;; At this point, we know FIRST points to the first key
> ;; which exists, or NIL.
> (loop :with last-good := first ; Keep the last good key
> :for the-cons :on (cddr first) :by #'cddr
> :do (progn
> (assert-proper-plist (cdr the-cons))
> (if (bad-key-p (car the-cons))
> (setf (cddr last-good)
> (cddr the-cons))
> (setf last-good the-cons)))
> :finally (return first)))))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: delete-from-plist.diff
Type: application/octet-stream
Size: 1925 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/alexandria-devel/attachments/20130223/3d7ee3ba/attachment.obj>
More information about the alexandria-devel
mailing list