简体   繁体   English

CAR表示缺点的*右*子树?

[英]CAR represent *right* subtree of a cons?

I am reading "ANSI Common Lisp" by Paul Graham, in $3.8 (page 40) it goes: 我正在阅读Paul Graham的“ANSI Common Lisp”,价格为3.8美元(第40页):

"Conses can also be considered as binary trees, with the car representing the right subtree and the cdr representing the left." “Conses也可以被视为二叉树,汽车代表正确的子树,cdr代表左边。”

To me it sounds like the "right" and "left" were used wrongly at opposite positions....then I took a look of the online errata but it's not one of the items listed there... 对我而言,听起来像“右”和“左”在相反的位置被错误地使用了......然后我看了一下在线勘误,但它不是那里列出的项目之一......

http://www.paulgraham.com/ancomliser.html http://www.paulgraham.com/ancomliser.html

Can anyone help to clarify this? 任何人都可以帮忙澄清一下吗?

Btw, on the next page (p41), Paul said that "Binary trees without interior nodes are not useful for much." 顺便说一下,在下一页(第41页),保罗说“没有内部节点的二叉树对它来说没用。” I don't fully understand it either. 我也不完全理解它。 what does it mean by "without interior nodes"? “没有内部节点”是什么意思? A deeply nested list can have as many internal/interior nodes (ie, conses) as you want, why he said "without"? 深度嵌套的列表可以包含任意数量的内部/内部节点(即,conses),为什么他说“没有”? or probably he just meant that these interior nodes, if present, does not contain atom values? 或者他只是意味着这些内部节点(如果存在)不包含原子值?

Thanks, /bruin 谢谢,/布鲁恩

In Lisp syntax, car is indeed the left half of a pair cdr the right half. 在Lisp语法中, car确实是一对cdr的左半部分是右半部分。

As for interior nodes, I suppose Graham means unlabeled interior nodes. 至于内部节点,我认为格雷厄姆意味着未标记的内部节点。 Eg you will much more often encounter trees like 例如,你会经常遇到像树一样的树

(+ (* x y) z)

which should be thought of as trees built out of triples, even though implemented in terms of pairs, than trees of the form 它应该被认为是由三元组构成的树,即使以对形式实现,也不是形式的树

((a . b) . (c . d))

Conses can also be considered as binary trees, with the car representing the right subtree and the cdr representing the left. Conses也可以被视为二叉树,汽车代表正确的子树,cdr代表左边。

You're right to pick up that this seems unconventional. 你是对的,这似乎是非常规的。 It should probably say that the car would represent the left subtree and that the cdr would represent the right subtree. 应该说car代表子树,而cdr代表正确的子树。 That said, trees (as well as lists) built from cons cells are intensional data structures. 从利弊细胞建也就是说,树(以及列表)是内涵的数据结构。 We make a decision about how to to represent structures using cons cells, and then think in terms of that representation, not in terms of the cons cells. 我们决定如何使用cons单元表示结构,然后根据该表示进行思考,而不是考虑cons单元。 So, when we're writing list processing code, we'd prefer 所以,当我们编写列表处理代码时,我们更喜欢

(defun mapcar1 (fn list)
  (cons (funcall fn (first list))
        (mapcar fn (rest list))))

to

(defun mapcar1 (fn list)
  (cons (funcall fn (car list))
        (mapcar fn (cdr list))))

because we think of a list as having a first element, and there being a rest of the list., even though both would work. 因为我们认为列表具有第一个元素,并且列表的其余部分 。即使两个都可以工作。 It's just a coincidence that because of implementation, car and cdr would work too. 这只是巧合,因为实施, carcdr也会起作用。 (Of course, this is a leaky abstraction when we notice that we have functions named, eg, mapcar and nthcdr instead of map (well, there is a map function, but it's a little different) and nthrest or nthtail . (当然,这是一个漏水的抽象时,我们注意到我们的功能命名,如, mapcarnthcdr而不是map (当然, 一个map功能,但它是一个有点不同),并nthrestnthtail

Similarly, we'd have to make a choice about representing binary trees with cons cells. 同样,我们必须选择使用cons单元表示二叉树。 It doesn't really make a difference whether you do: 你是否真的没有区别:

(defun make-tree (left right)
  (cons left right))

(defun left (tree)
  (car tree))

(defun right (tree)
  (cdr tree))

or 要么

(defun make-tree (left right)
  (cons right left))

(defun left (tree)
  (cdr tree))

(defun right (tree)
  (car tree))

because you ought to be using make-tree , left , and right rather than cons , car , and cdr when you're working with trees. 因为当你在树上工作时,你应该使用make-treeleftright而不是conscarcdr

Binary trees without interior nodes are not useful for much. 没有内部节点的二叉树没有多大用处。

He's referring to binary trees whose internal nodes don't have values of their own. 他指的是二进制树,其内部节点没有自己的值。 For instance, in a binary search tree, a node doesn't only have a left and right subtree, it has an associated value (or element). 例如,在二叉搜索树中,节点不仅具有左右子树,还具有关联的值(或元素)。 A binary search tree node is really a triple (element, left, right), not a pair (left, right). 二叉搜索树节点实际上是三元组 (元素,左,右),而不是一对(左,右)。 Some problems can be solved with binary trees whose nodes don't have an associated value, but for many problems, you'll want nodes that hold two pointers (to left and right subtrees) in addition to a value. 使用其节点没有关联值的二叉树可以解决一些问题,但是对于许多问题,除了值之外,您还需要包含两个指针(左右子树)的节点。

If you represent a (binary) tree with some form of nodes, we have several possible ways to represent them in Common Lisp. 如果您使用某种形式的节点表示(二进制)树,我们有几种可能的方法在Common Lisp中表示它们。

We could define a node structure: 我们可以定义一个节点结构:

(defstruct node left right)

Then we have a function MAKE-NODE . 然后我们有一个函数MAKE-NODE

We could define a node class: 我们可以定义一个节点类:

(defclass node ()
  (left right))

Nodes would be made with (make-instance 'node) . 节点将使用(make-instance 'node)

We could make nodes with lists: 我们可以使用列表创建节点:

(defun make-node (left right)
  (list left right))

Above uses two cons cells. 以上使用两个cons单元格。

We could make nodes for a binary tree a bit smaller with just one cons cell: 我们可以只使用一个cons单元格为二叉树创建一个小的节点:

(defun make-node (left right)
  (cons left right))

We could make nodes as a vector: 我们可以将节点作为向量:

(defun make-node (left right)
  (vector left right))

There are many possibilities. 有很多种可能性。 If the node should also have some other information, then the single cons cell approach is not enough. 如果节点还应该有其他信息,那么单一的cons单元方法是不够的。 Something like a structure or class is fine, since the data item can have more information and the object knows its type: we can easily ask (node-p something) and get a useful answer. 像结构或类这样的东西很好,因为数据项可以有更多信息,而对象知道它的类型:我们可以轻松地询问(node-p something)并获得有用的答案。

The style rules for choosing the right data structure for any slightly more advanced software you want to write: 用于为要编写的任何稍高级软件选择正确数据结构的样式规则:

  • by default use CLOS 默认情况下使用CLOS
  • if CLOS is too slow (for example slot access is too slow), then try to optimize CLOS 如果CLOS太慢(例如插槽访问太慢),则尝试优化CLOS
  • if CLOS is still too slow, then use structures. 如果CLOS仍然太慢,那么使用结构。 Slot access should be faster 插槽访问应该更快
  • try to avoid representing data structures as untyped lists or cons trees 尽量避免将数据结构表示为无类型列表或缺点树

IMO, it would have been better if the text had said simply: 国际海事组织,如果案文简单地说:

Conses can also be considered as binary trees, with the car representing one subtree and the cdr representing the other subtree. Conses也可以被视为二叉树,汽车代表一个子树,cdr代表另一个子树。

Which is chosen for left and which for right is arbitrary. 左边选哪个,右边选哪个是任意的。 (Of course, consistency etc.) Perhaps the text had already introduced a concrete representation? (当然,一致性等)或许文本已经引入了具体的表述? Or perhaps it did so later, and needed to refer to which was which? 或许它之后会这样做,需要参考哪个是哪个? If not -- if that statement was all there was, then I think there is no reason to choose sides. 如果没有 - 如果那个陈述完全存在,那么我认为没有理由选择双方。

He is just being cute when he asserts that the car is the right and the cdr is the left? 当他声称汽车是正确的并且cdr是左边时,他只是很可爱?

Recall that car/cdr arose originally on the IBM 704. On that machine the car, ie the address part, of the words was the right side. 回想一下,汽车/ cdr最初是在IBM 704上产生的。在那台机器上,汽车,即地址部分,是正确的。 Figure 4 on page 8 of this one of the 704 manuals illustrates that. 704手册中的这一个的第8页图4说明了这一点。 So I guess his presentation has some historical validity. 所以我猜他的演讲有一些历史的有效性。

But I'd be curious if he actually has illustrations of lists like '(abcd) drawn out using his left/right convention. 但我很好奇他是否真的有像(abcd)使用他的左/右惯例绘制的列表的插图。

It is an error. 这是一个错误。 The reason why it is an error is that conses correspond to a printed notation, and that printed notation goes left to right in a particular way. 它是错误的原因是conses对应于打印的符号,并且打印的符号以特定方式从左到右。

Example: 例:

(a b c d) <==> (a . (b . (c . (d . nil))))

This corresponds to the tree structure: 这对应于树结构:

   .
  / \
 a   .
    / \
   b   .
      / \
     c   .
        / \
       d   nil

A tree is not a simple graph; 树不是简单的图形; the children are ordered. 孩子们订购了。

If you say that (a . b) is a node with a left child b and right child a , it goes against the convention of the notation you are using , the meaning of left-and-right, and the direction of writing you're using. 如果你说(a . b)是一个带有左子b和右子a的节点,那就违背了你正在使用的符号的惯例 ,左右的含义以及写你的方向'重新使用。

If we are discussing Lisp, the notation is given : car -s are printed on the left, preceding the rest of the list. 如果我们讨论Lisp, 则给出符号car -s打印在左侧,在列表的其余部分之前。 Mixing it up is not properly descriptive of the situation in Lisp, where we have to take into account everything, including the correspondence between symbolic expressions and internal structure. 将它混合起来并没有恰当地描述Lisp中的情况,我们必须考虑到所有内容,包括符号表达式和内部结构之间的对应关系。

If you're using Lisp conses to implement a binary data structure, and you do not care about any correspondence to Lisp's printed representation, you can assign left and right to car and cdr whichever way you like, of course, and the algorithm will work out. 如果你使用Lisp conses来实现二进制数据结构,并且你不关心任何与Lisp的打印表示的对应关系,你可以左右分配carcdr你喜欢哪种方式,当然,算法将工作出。 The convention in your code is not descriptive of the Lisp language, though. 但是,代码中的约定并不描述Lisp语言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM