屬性清單
普通列表對於表示元素序列很有用,但有時表示一種鍵值對映更有幫助。Common Lisp 提供了幾種方法,包括真正的雜湊表(參見 18.1 雜湊表概念 )。在 Common Lisp 中有兩種主要方式或表示值對映的鍵: 屬性列表和關聯列表 。此示例描述了屬性列表。
屬性列表或 plist 是一個普通列表,其中交替值被解釋為鍵及其關聯值。例如:
(defparameter *ages* (list 'john 34 'mary 23 'tim 72))
可以被視為屬性列表,其將表示個人姓名的符號與表示年齡的整數對映。可以使用簡單列表函式(如 member) 實現一些檢索功能。例如,要檢索約翰的年齡,可以寫
(second (member 'mary *age*))
;=> 23
所述構件函式返回開頭的列表的尾部瑪麗,也就是 (瑪麗 23 添 72) ,和第二返回該列表的第二個元素,即 23 。雖然這是訪問屬性列表中的值的一種方法,但像屬性列表這樣的約定的目的是從底層表示(列表)中抽象出來,並提供用於處理資料結構的更高階函式。
對於屬性列表,檢索函式是 getf ,它接受屬性列表,一個鍵(通常稱為指示符 ),以及在屬性列表不包含鍵值的情況下返回的可選預設值。
(getf *ages* 'tim)
;=> 72
(getf *ages* 'bob -1)
;=> -1
要更新屬性列表中的值,可以使用 setf 。例如,當約翰的生日到來並且他的年齡增加時,可以執行以下任一操作:
(setf (getf *ages* 'john) 35)
(incf (getf *ages* 'john))
incf 適用於這種情況,因為它基於 setf 。
要在屬性列表中查詢多個屬性,請使用 get-properties 。
所述 GETF 功能通過列表搜尋從左至右,這意味著是能夠掩模值的屬性列表,而無需從一個列表中去除它們或更新的任何列表中的結構。例如,使用 list * :
(defvar *ages* '(john 34 mary 23 tim 72))
(defvar *new-ages* (list* 'mary 29 *ages*))
*new-ages*
;=> (mary 29 john 34 mary 23 tim 72)
現在,對 mary 的查詢將返回第一個條目:
(getf *new-ages* 'mary)
;=> 29