From 048de2e545042c94287797f9c029c88606591cf5 Mon Sep 17 00:00:00 2001
From: Attila Lendvai <attila.lendvai@gmail.com>
Date: Tue, 4 Mar 2014 13:41:20 +0600
Subject: [PATCH] Optimize DELETE-FROM-PLIST not to cons.

Patch by "James M. Lawrence" <llmjjmll@gmail.com>
---
 lists.lisp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lists.lisp b/lists.lisp
index 00b42fa..feaa726 100644
--- a/lists.lisp
+++ b/lists.lisp
@@ -278,8 +278,20 @@ not destructively modified. Keys are compared using EQ."
 (defun delete-from-plist (plist &rest keys)
   "Just like REMOVE-FROM-PLIST, but this version may destructively modify the
 provided plist."
-  ;; FIXME: should not cons
-  (apply 'remove-from-plist plist keys))
+  (declare (optimize speed))
+  (loop with head = plist
+        with tail = nil   ; a nil tail means an empty result so far
+        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
+               (symbol-macrolet ((next (cdr rest)))
+                 (if tail
+                     (setf (cdr tail) next)
+                     (setf head next)))
+               ;; keep this pair
+               (setf tail rest))
+        finally (return head)))
 
 (define-modify-macro remove-from-plistf (&rest keys) remove-from-plist
                      "Modify macro for REMOVE-FROM-PLIST.")
-- 
GitLab