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