Reputation: 6338
I have a property list:
(setf *star* '(:points 5))
I'd like to modify this plist. Sometimes the better choice is to do mutation, and sometimes the better choice is to use an immutable update.
How to modify the plist using mutation?
(mutate *star* :points 6)
*star* ; '(:points 6)
And how to modify the plist using an immutable update?
(update *star* :points 6) ; '(:points 6)
*star* ; '(:points 5)
Upvotes: 3
Views: 1234
Reputation: 2671
To mutate a plist, just use setf
:
(setf (getf *star* :points) 59)
To do a non-mutative update, where the original value is left undisturbed, you might do something like this:
(defun update-plist (plist indicator new-value)
(let ((other-properties nil))
(loop while plist
for property = (pop plist)
for value = (pop plist)
when (eq property indicator)
do (return-from update-plist (list* property new-value
(append other-properties plist)))
else do (push value other-properties)
(push property other-properties))
(list* indicator new-value other-properties)))
It differs from your example:
*star* ;; (:points 6 :color :green)
(update-plist *star* :points 5) ;; (:points 5 :color :green)
*star* ;; (:points 6 :color :green) -- Doesn't change.
Upvotes: 2
Reputation: 60014
What you are looking for are getf
and maybe get-properties
.
To modify the plist non-destructively, use list*
:
(setq *star* (list* :points 6 *star*))
If your plist is associated with a symbol, you should use get
and remprop
.
NB: it is a much better idea to use association lists (see assoc
and acons
) because they are more flexible (e.g., it is easier to switch from associating multiple objects with a key using alists).
Upvotes: 4