Looks good! Much cleaner/better. -Robert
On Sun, Feb 24, 2013 at 6:30 AM, James M. Lawrence <llmjj...@gmail.com> wrote: > On Sat, Feb 23, 2013 at 4:09 AM, Robert Smith <q...@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@common-lisp.net > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel _______________________________________________ alexandria-devel mailing list alexandria-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel