2

我有一个财产清单

(setf *star* '(:points 5))

我想修改这个 plist。有时更好的选择是进行突变,有时更好的选择是使用不可变更新。

如何使用突变修改 plist ?

(mutate *star* :points 6)
*star* ; '(:points 6)

以及如何使用不可变更新修改plist

(update *star* :points 6) ; '(:points 6)
*star*                    ; '(:points 5)
4

2 回答 2

4

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).

于 2015-09-13T18:06:40.290 回答
2

要改变 plist,只需使用setf

(setf (getf *star* :points) 59)

要进行非可变更新,在原始值不受干扰的情况下,您可以执行以下操作:

(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)))

它与您的示例不同:

*star* ;; (:points 6 :color :green)
(update-plist *star* :points 5) ;; (:points 5 :color :green)
*star* ;; (:points 6 :color :green) -- Doesn't change.
于 2015-09-17T01:38:31.670 回答