我正在阅读“Land of Lisp”(顺便提一下,这是我读过的最好的技术书籍之一)而且我遇到了关联列表
(defparameter *edges*
'((living-room (garden west door)
(attic upstairs ladder))
(garden (living-room east door))
(attic (living-room downstairs ladder))))
首先,Lisp中的关联列表与Java的Map(键值绑定)的概念相同吗? 对于客厅钥匙,如何拥有多个价值?为什么不用列表包含值:
(living-room ((garden west door) (attic upstairs ladder)))
答案 0 :(得分:13)
是的,关联列表是表达键值关联的一种方式。 Common Lisp为此提供的其他结构是属性列表和哈希表。
该值实际上已包含在列表中。 alist基本上是对的列表,其中每对的汽车是钥匙,而cdr是与该钥匙相关联的值。如果您使用ASSOC查找关键的LIVING-ROOM并将CDR应用于结果:
CL-USER> (cdr (assoc 'living-room *edges*)) ((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
这背后的魔力在于这样一个事实,即一辆汽车为living-room
并且其cdr是两个元素(garden west door)
和(attic upstairs ladder)
的列表的一对也可被视为三个 - 元素列表(living-room (garden west door) (attic upstairs ladder))
,因为列表是由成对构建的。
通常,当将alists表示为带引号的对象时,您会看到用虚线对显式描述的元素,而不是使用列表符号,例如:
(defparameter *edges* '((living-room . ((garden west door) (attic upstairs ladder))) (garden . ((living-room east door))) (attic . ((living-room downstairs ladder))) ))
答案 1 :(得分:5)
ASSOC返回cons单元格,因此包括键和值。
原因是这样可以轻松地破坏性地更新值(或键)。
此处更新隐藏在SETF后面:
CL-USER 11 > (defparameter *edges*
(copy-tree
'((living-room (garden west door)
(attic upstairs ladder))
(garden (living-room east door))
(attic (living-room downstairs ladder)))))
*EDGES*
CL-USER 12 > (assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
CL-USER 13 > (cdr (assoc 'living-room *edges*))
((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
CL-USER 14 > (setf (cdr (assoc 'living-room *edges*)) '((garden east door)))
((GARDEN EAST DOOR))
CL-USER 15 > (cdr (assoc 'living-room *edges*))
((GARDEN EAST DOOR))
答案 2 :(得分:1)
首先,Lisp中的关联列表与Java的Map(键值绑定)的概念相同吗?
Java的Map是一个界面。 alist是使用(链接)列表存储键值对的特定方式。我不认为Java有任何内置映射具有与alist相同的属性,但编写一个并不难。由于alist是一个列表,列表的所有功能和属性仍然存在。
对于客厅钥匙,如何才能拥有多个价值?为什么不用列表包含值:
alist不是Lisp语法的一部分。它只是一个列表,因此您可以在每个元素的CDR中放置您想要的任何内容。在这种情况下,它是另一个CONS细胞。 ASSOC
只关注每个元素的CAR。
(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
答案 3 :(得分:1)
关联列表在概念上与地图类似,只要将关键字与值相关联。
不需要在另一个列表中包含多个值,因为这会更改值的含义。我对这本书并不熟悉,但似乎*EDGES*
的定义方式,作者希望
(cdr (assoc 'Foobar *edges*))
是您可以从Foobar获得的地方列表。根据定义,如果存在单个或多个值,则为真。
如果,当有多个值时,您将这些值嵌套在另一个列表中,那么当您想要使用它们时,您只需从该列表中选择它们。它不会给你任何东西,它会使它与单值案例不同。