diff --git a/lists.lisp b/lists.lisp
index 00b42fafdbaf0ca11af11640507fea270780ff4c..feaa72633607e0e43a947cd190734b0096c29d45 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.")