我在Common Lisp中有以下设置。 my-object
是5个二叉树的列表。
(defun make-my-object ()
(loop for i from 0 to 5
for nde = (init-tree)
collect nde))
每个二叉树都是大小为3的列表,其中包含node
,左子项和右子项
(defstruct node
(min 0)
(max 0)
(ctr 0))
(defun vals (tree)
(car tree))
(defun left-branch (tree)
(cadr tree))
(defun right-branch (tree)
(caddr tree))
(defun make-tree (vals left right)
(list vals left right))
(defun init-tree (&key (min 0) (max 1))
(let ((n (make-node :min min :max max)))
(make-tree n '() '())))
现在,我试图手动将一个元素添加到其中一个二叉树中,如下所示:
(defparameter my-object (make-my-object))
(print (left-branch (car my-object))) ;; returns NIL
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
(print (left-branch (car my-object))) ;; still returns NIL
对print
的第二次调用仍会返回NIL
。为什么是这样?如何在二叉树中添加元素?
答案 0 :(得分:4)
第一个功能就是:
(defun make-my-object ()
(loop repeat 5 collect (init-tree)))
现在您为node
定义了一个结构,但是您使用树和 my-object 的列表?为什么他们没有结构?
而不是car
,cadr
和caddr
可以使用first
,second
,third
。
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
您将局部变量x
设置为新值。为什么?在let
之后,局部变量也消失了。为什么不设置左分支呢?您需要定义一种方法。请记住:Lisp函数返回值,而不是您稍后可以设置的内存位置。如何更改列表中的内容?更好的是:使用结构并更改槽值。结构(甚至CLOS类)优于普通列表:对象带有类型,槽名称,创建访问器,创建make函数,创建类型谓词,...
无论如何,我会为node,tree和 object 定义结构或CLOS类......
答案 1 :(得分:2)
此问题中的大多数代码对于此处的实际问题并不重要。真正的问题在于对这段代码的误解:
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
如果没有任何类型的用户定义结构,我们可以看到相同的行为:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(let ((x (car cell)))
(setf x 3)
(print cell))) ; prints (1 . 2)
如果您理解为什么两个印刷语句都会生成(1.2),那么您已经足够理解为什么您自己的代码不会执行您(之前)预期的操作它要做。
这里有两个变量:单元格和 x 。有三个值我们关注 1 , 2 ,以及通过调用(cons 1 2)生成的cons-cell 。 Lisp中的变量通常称为绑定;变量或名称绑定到一个值。变量 cell 绑定到cons单元(1.2)。当我们进入内部let时,我们评估(car cell)以产生值 1 ,然后绑定到变量 X 即可。然后,我们为变量 x 分配一个新值 3 。这并不会修改包含 x 最初绑定的值的cons单元格。实际上,最初绑定到 x 的值是由(汽车单元格)生成的,一旦返回(汽车单元格)的调用,重要的唯一值是 1 。
如果您有其他编程语言方面的经验,这与
类似int[] array = ...;
int x = array[2]; // read from the array; assign result to x
x = 42; // doesn't modify the array
如果要修改结构,则需要 setf 结构的相应部分。 E.g:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(setf (car cell) 3)
(print cell)) ; prints (3 . 2)