Lisp 中槽的访问问题(CLOS)
我有一个 Node 类,它有一个“元素”槽,其中包含一个包含数字和一个字母的列表,例如:
“(1 2 3 b 4 5 6)
(defclass node ()
((element :reader get-element
:writer set-element
:initform '()
:initarg :element
:documentation "The element"))
程序的一部分应该采用“元素”槽,将字母与数字之一交换,最后创建一个新的 Node 对象,并将交换的列表作为其“元素”槽。我已经有一个交换函数,它接收一个列表和该列表的两个成员,并使用rotatef 函数交换它们。
为了测试交换函数是否正常工作,我创建了以下代码段,它将元素存储在临时变量中,并将字母“b”与列表中的数字交换:
(setf root (make-instance 'node))
(set-element '(1 2 3 b 4 5 6 7 8) root)
(setf temp(获取元素根))
(交换温度 'b 4)
问题在于根对象的“元素”槽与 temp 一起交换。奇怪的是,我尝试将交换功能更改为反向,但它没有修改两者中的任何一个。
我不知道是否有任何方法可以将插槽分配给变量或防止上述情况发生。
谢谢。
I have a Node class that has an 'element' slot which contains a list with numbers and one letter, for example:
'(1 2 3 b 4 5 6)
(defclass node ()
((element :reader get-element
:writer set-element
:initform '()
:initarg :element
:documentation "The element"))
Part of the program is supposed to take the 'element' slot, swap the letter with one of the numbers and finally create a new Node object with the swapped list as its 'element' slot. I already have a swap function that receives a list and two members of that list and using the rotatef function it swaps them.
To test that the swap function was working I created the following piece of code which stores in a temporary variable the element and swaps the letter 'b' with a number in the list:
(setf root (make-instance 'node))
(set-element '(1 2 3 b 4 5 6 7 8) root)
(setf temp (get-element root)) (swap temp 'b 4)
The problem is that the 'element' slot of the root object is swapped along with temp. Strangely I tried changing the swap function to reverse and it doesn't modify any of the two.
I don't know if there's any way to assign a slot to a variable or a way to prevent the above from happening.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
其他一些备注:
使用访问器方法而不是 getter 和 setter 方法。这通常是首选。
列表是使用 LIST 或 COPY-LIST 等函数创建的。写为 '(1 b 2) 的列表在源代码中是文字常量,不应更改。 CL 标准中未定义如果尝试更改文字列表会发生什么情况。这可能会产生不良影响。如果您有一个文字列表并且想要修改它,则应首先使用 COPY-LIST(或 COPY-TREE)复制它并修改该副本。
您还需要了解 REVERSE 等非破坏性操作与 NREVERSE 等可能破坏性操作之间的区别。如果希望原始列表不变,请使用非破坏性操作。列表或序列操作的性质在 Common Lisp Hyperspec 中针对每个操作进行了描述。
Some other remarks:
instead of a getter and setter method, use an accessor method. That's usually preferred.
lists are created with functions like LIST or COPY-LIST. A list written as '(1 b 2) is in source code a literal constant and should not be changed. It is undefined in the CL standard what happens if you try to change a literal list. This can have unwanted effects. If you have a literal list and you want to modify it, you should first copy it with COPY-LIST (or COPY-TREE) and modify that copy.
you also need to learn the difference between non-destructive operations like REVERSE and possibly destructive operations like NREVERSE. If you want the original list to be unchanged, use non-destructive operations. The nature of the list or sequence operations is described in the Common Lisp Hyperspec for each operation.
Reverse
创建并返回一个新列表。Rotatef
(就像setf
、incf
等)修改一个地方。您必须复制列表
或复制树
您的元素
来创建一个新列表,然后进行修改。Reverse
creates and returns a new list.Rotatef
(just assetf
,incf
and the like) modify a place. You will have tocopy-list
orcopy-tree
yourelement
to create a new list that you then modify.