在Lisp(CLOS)中访问插槽的问题

时间:2010-09-25 23:00:02

标签: lisp common-lisp clos

我有一个Node类,它有一个'element'插槽,其中包含一个带有数字和一个字母的列表,例如:

'(1 2 3 b 4 5 6)


(defclass node ()
  ((element :reader get-element
            :writer set-element
            :initform '()
            :initarg :element
            :documentation "The element"))

该程序的一部分应该采用'element'插槽,将字母与其中一个数字交换,最后创建一个新的Node对象,将交换列表作为其“元素”插槽。我已经有一个交换函数,它接收一个列表和该列表的两个成员,并使用rotatef函数交换它们。

为了测试交换功能是否正常工作,我创建了以下代码,该代码在临时变量中存储元素,并将字母'b'与列表中的数字交换:


(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)

问题是根对象的'element'槽与temp一起交换。奇怪的是,我尝试将交换功能更改为反向,并且不会修改这两者中的任何一个。

我不知道是否有任何方法可以为变量分配插槽或防止上述情况发生。

感谢。

2 个答案:

答案 0 :(得分:3)

其他一些评论:

  • 使用访问器方法代替getter和setter方法。这通常是首选。

  • 使用LIST或COPY-LIST等功能创建列表。写为'(1 b 2)的列表在源代码中是文字常量,不应更改。在CL标准中未定义如果您尝试更改文字列表会发生什么。这会产生不良影响。如果您有文字列表并且想要修改它,则应首先使用COPY-LIST(或COPY-TREE)复制它并修改该副本。

  • 您还需要了解REVERSE等非破坏性操作与NREVERSE等破坏性操作之间的区别。如果希望原始列表保持不变,请使用非破坏性操作。每个操作的Common Lisp Hyperspec中描述了列表或序列操作的性质。

答案 1 :(得分:2)

Reverse创建并返回一个新列表。 Rotatef(就像setfincf等)修改地点。您必须copy-listcopy-tree element创建一个新修改的列表。