Lisp“关联列表”与“关联列表”之间的关系是什么?以及像 Java 的 Map 那样的键值映射?

发布于 2024-10-02 15:04:28 字数 566 浏览 7 评论 0原文

我正在阅读《Land of Lisp》(顺便说一句,这是我读过的最好的技术书籍之一),并且我遇到了“关联列表”:

(defparameter *edges* 
  '((living-room (garden west door) 
                 (attic upstairs ladder))
    (garden (living-room east door)) 
    (attic (living-room downstairs ladder))))

Is an Association list in Lisp the与Java的Map(键值绑定)相同的概念吗?

对于 living-room 键,怎么可能有多个值?为什么用列表括住值?

'(living-room
   ((garden west door)
    (attic upstairs ladder)))

I'm reading Land of Lisp (which is by the way, one of the best technical books I have ever read) and I have come across the "association list":

(defparameter *edges* 
  '((living-room (garden west door) 
                 (attic upstairs ladder))
    (garden (living-room east door)) 
    (attic (living-room downstairs ladder))))

Is an association list in Lisp the same concept of Java's Map (key-value binding)?

For living-room key, how it is possible to have more than one value? Why enclose the value with a list?

'(living-room
   ((garden west door)
    (attic upstairs ladder)))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷默言语 2024-10-09 15:04:28
  1. 是的,关联列表是表达键值关联的一种方式。 Common Lisp 为此提供的其他结构是属性列表和哈希表。

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

CL-USER> (cdr (assoc 'living-room *edges*))
((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

这背后的神奇之处在于,一对汽车是“living-room”且其 cdr 是以下列表的事实:两个元素(花园西门)(阁楼上的梯子)也可以被视为三元素列表(客厅(花园西门)(阁楼楼上的梯子)),由于列表是成对构造的。

通常,当将列表表示为带引号的对象时,您会看到用点对明确描述的元素,而不是用列表符号进行双关,如下所示:

(defparameter *edges* 
  '((living-room . ((garden west door)
                    (attic upstairs ladder)))
    (garden . ((living-room east door))) 
    (attic . ((living-room downstairs ladder))) ))
  1. Yes, the association list is one way to express key-value associations. Other structures Common Lisp provides to that end are property lists and hash tables.

  2. The value is actually already contained in a list. An alist is fundamentally a list of pairs, where the car of each pair is the key, and the cdr is the value associated with that key. If you look up the key LIVING-ROOM with ASSOC and apply CDR to the result:

CL-USER> (cdr (assoc 'living-room *edges*))
((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

The magic behind this lies in the fact that a pair whose car is living-room and whose cdr is a list of the two elements (garden west door) and (attic upstairs ladder) can also be viewed as the three-element list (living-room (garden west door) (attic upstairs ladder)), due to the way lists are constructed out of pairs.

Usually when representing alists as quoted objects, you see the elements depicted explicitly with dotted pairs, rather than punning with list notation, like so:

(defparameter *edges* 
  '((living-room . ((garden west door)
                    (attic upstairs ladder)))
    (garden . ((living-room east door))) 
    (attic . ((living-room downstairs ladder))) ))
弱骨蛰伏 2024-10-09 15:04:28

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))

ASSOC returns the cons cell and thus includes both key and value.

The reason is that this makes it easy to update the value (or the key) destructively.

Here the update is hidden behind 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))
海风掠过北极光 2024-10-09 15:04:28

首先,Lisp中的关联列表和Java的Map(键值绑定)是同一个概念吗?

Java的Map是一个接口。 alist 是一种使用(链接)列表来存储键值对的特定方式。我不认为 Java 有任何与 alist 具有相同属性的内置 Map,但编写一个并不难。由于 alist 是一个列表,因此列表的所有功能和属性仍然有效。

对于客厅钥匙,怎么可能有多个值?为什么不将值括在列表中:

alist 不是 Lisp 语法的一部分。它只是一个列表,因此您可以将任何内容放入每个元素的 CDR 中。在本例中,它是另一个 CONS 单元。 ASSOC 只是查看每个元素的 CAR。

(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

First, is association list in Lisp the same concept of Java's Map (key-value binding)?

Java's Map is an interface. An alist is a specific way of using a (linked) list to store key-value pairs. I don't think Java has any built-in Maps that have the same properties as an alist, but it wouldn't be hard to write one. Since an alist is a list, all of the functions and properties of lists still hold.

For living-room key, how it is possible to have more than one value? why not to enclose the value with a list:

An alist isn't part of Lisp syntax. It's just a list, so you can put whatever you want in the CDR of each element. In this case, it's another CONS cell. ASSOC just looks at the CAR of each element.

(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
泅渡 2024-10-09 15:04:28

关联列表在概念上与映射类似,两者都将键与值相关联。

无需将多个值包含在另一个列表中,因为这会改变该值的含义。我对这本书不熟悉,但似乎 *EDGES* 的定义方式,作者希望

(cdr (assoc 'Foobar *edges*))

成为您可以从 Foobar 获取的位置的列表。根据定义,如果存在单个或多个值,则情况如此。

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

An association list is similar in concept to a map, insofar as both associate keys with values.

There's no need to enclose multiple values in another list, because that changes the meaning of the value. I'm not familiar with this book, but it seems that the way that *EDGES* is defined, the author wants

(cdr (assoc 'Foobar *edges*))

to be a list of places that you can get from Foobar. As defined, this is true if there are single or multiple values.

If, when there were multiple values, you nested those values in another list, then you'd just have to pick them out of that list when you wanted to use them. It wouldn't give you anything, and it would make it different from the single value case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文