属性清单

普通列表对于表示元素序列很有用,但有时表示一种键值映射更有帮助。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