1

我有一个 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 (get-element root)) (swap temp 'b 4)

问题是根对象的“元素”插槽与临时交换。奇怪的是,我尝试将交换功能更改为反转,它不会修改两者中的任何一个。

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

谢谢。

4

2 回答 2

3

其他一些评论:

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

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

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

于 2010-09-25T23:21:50.007 回答
2

Reverse创建并返回一个新列表。 Rotatef(就像setfincf等等)修改一个地方。您将不得不copy-listcopy-treeelement创建一个新列表,然后进行修改。

于 2010-09-25T23:11:20.640 回答