Lisp中的赋值

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

我在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 (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。我们关注的三个值是12,以及调用(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。我们关注的三个值是12,以及调用(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;//不修改数组