Lisp中的赋值
我在Common Lisp中有以下设置<代码>我的对象是由5个二叉树组成的列表Lisp中的赋值,lisp,common-lisp,assign,Lisp,Common Lisp,Assign,我在Common Lisp中有以下设置我的对象是由5个二叉树组成的列表 (defun make-my-object () (loop for i from 0 to 5 for nde = (init-tree) collect nde)) 每个二叉树都是一个大小为3的列表,其中包含一个节点、一个左子树和一个右子树 (defstruct node (min 0) (max 0) (ctr 0)) (defun vals
(defun make-my-object ()
(loop for i from 0 to 5
for nde = (init-tree)
collect nde))
每个二叉树都是一个大小为3的列表,其中包含一个节点
、一个左子树和一个右子树
(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
。为什么会这样?如何向二叉树中添加元素?第一个函数就是:
(defun make-my-object ()
(loop repeat 5 collect (init-tree)))
现在您为节点定义了一个结构,但是您使用了树和我的对象的列表吗?为什么它们不是结构
除了car
,cadr
和caddr
之外,我们将使用第一个,第二个,第三个
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
将局部变量x
设置为新值。为什么?在let
之后,局部变量也消失了。为什么不改为设置左分支?您需要定义这样做的方法。请记住:Lisp函数返回值,而不是以后可以设置的内存位置。如何更改列表中的内容?更好的方法是:使用结构并更改插槽值。与普通列表相比,该结构(甚至CLOS类)具有以下优势:对象携带类型、插槽命名、访问器创建、make函数创建、类型谓词创建
无论如何,我会为节点、树和对象定义结构或CLOS类…第一个函数就是:
(defun make-my-object ()
(loop repeat 5 collect (init-tree)))
现在您为节点定义了一个结构,但是您使用了树和我的对象的列表吗?为什么它们不是结构
除了car
,cadr
和caddr
之外,我们将使用第一个,第二个,第三个
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
将局部变量x
设置为新值。为什么?在let
之后,局部变量也消失了。为什么不改为设置左分支?您需要定义这样做的方法。请记住:Lisp函数返回值,而不是以后可以设置的内存位置。如何更改列表中的内容?更好的方法是:使用结构并更改插槽值。与普通列表相比,该结构(甚至CLOS类)具有以下优势:对象携带类型、插槽命名、访问器创建、make函数创建、类型谓词创建
不管怎样,我会为节点、树和对象定义结构或CLOS类…这个问题中的大多数代码对于这里的实际问题不是必需的。真正的问题在于对该准则的误解:
(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)
如果您理解了为什么两个print语句都会产生(1.2),那么您就足够理解为什么您自己的代码没有达到您(以前)期望的效果
这里有两个变量:单元格和x。我们关注的三个值是1、2,以及调用(cons 1 2)生成的cons单元格。Lisp中的变量通常称为绑定;变量或名称绑定到一个值。变量单元格绑定到cons单元格(1.2)。当我们进入内部let时,我们计算(car cell)以生成值1,然后将该值绑定到变量x。然后,我们给变量x分配一个新值3。这不会修改包含x最初绑定到的值的cons单元格。实际上,最初绑定到x的值是由(car cell)生成的,一旦调用(car cell)返回,唯一重要的值就是1
如果您在其他编程语言方面有一些经验,这与
int[]数组=。。。;
int x=数组[2];//从数组中读取;将结果分配给x
x=42;//不修改数组
如果要修改结构,需要设置结构的适当部分。例如:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(setf (car cell) 3)
(print cell)) ; prints (3 . 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)
如果您理解了为什么两个print语句都会产生(1.2),那么您就足够理解为什么您自己的代码没有达到您(以前)期望的效果
这里有两个变量:单元格和x。我们关注的三个值是1、2,以及调用(cons 1 2)生成的cons单元格。Lisp中的变量通常称为绑定;变量或名称绑定到一个值。变量单元格绑定到cons单元格(1.2)。当我们进入内部let时,我们计算(car cell)以生成值1,然后将该值绑定到变量x。然后,我们给变量x分配一个新值3。这不会修改包含x最初绑定到的值的cons单元格。实际上,最初绑定到x的值是由(car cell)生成的,一旦调用(car cell)返回,唯一重要的值就是1
如果您在其他编程语言方面有一些经验,这与
int[]数组=。。。;
int x=数组[2];//从数组中读取;将结果分配给x
x=42;//不修改数组