关于Lisp中关联列表的基本问题

时间:2010-11-11 13:02:58

标签: lisp common-lisp land-of-lisp

我正在阅读“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)))

4 个答案:

答案 0 :(得分:13)

  1. 是的,关联列表是表达键值关联的一种方式。 Common Lisp为此提供的其他结构是属性列表和哈希表。

  2. 该值实际上已包含在列表中。 alist基本上是对的列表,其中每对的汽车是钥匙,而cdr是与该钥匙相关联的值。如果您使用ASSOC查找关键的LIVING-ROOM并将CDR应用于结果:

  3. 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获得的地方列表。根据定义,如果存在单个或多个值,则为真。

如果,当有多个值时,您将这些值嵌套在另一个列表中,那么当您想要使用它们时,您只需从该列表中选择它们。它不会给你任何东西,它会使它与单值案例不同。