Re: [alexandria-devel] Implementation of DELETE-FROM-PLIST

2013-02-24 Thread Zach Beane
James M. Lawrence llmjj...@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

Zach

___
alexandria-devel mailing list
alexandria-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel


Re: [alexandria-devel] Implementation of DELETE-FROM-PLIST

2013-02-24 Thread Stas Boukarev
Zach Beane x...@xach.com writes:

 James M. Lawrence llmjj...@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)))

-- 
With best regards, Stas.

___
alexandria-devel mailing list
alexandria-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel


Re: [alexandria-devel] Implementation of DELETE-FROM-PLIST

2013-02-24 Thread Robert Smith
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