[alexandria-devel] Implementation of DELETE-FROM-PLIST
Robert Smith
quad at symbo1ics.com
Sun Feb 24 23:11:24 UTC 2013
Looks good! Much cleaner/better.
-Robert
On Sun, Feb 24, 2013 at 6:30 AM, James M. Lawrence <llmjjmll at gmail.com> wrote:
> On Sat, Feb 23, 2013 at 4:09 AM, Robert Smith <quad at symbo1ics.com> wrote:
>>
>> (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)))))
>
> 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)))
>
> _______________________________________________
> alexandria-devel mailing list
> alexandria-devel at common-lisp.net
> http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel
More information about the alexandria-devel
mailing list