使用访问者功能 nth 时遇到问题。我将一个列表传递给某个函数并使用 nth 对函数列表中的元素进行新绑定,然后当我从函数中调用该列表时,它被修改,并且它不是我的想!会发生什么?
一些例子
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1
我理解上面发生了什么,但是如果我们将所有内容更改为列表,那么就会发生一些我无法理解的事情
(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)
我期望a为(1),为什么它被修改了?我还尝试了其他功能,如 car 和 first ,结果是一样的。
PS,我在Lispworks和SBCL中尝试过,结果相同。
答案 0 :(得分:4)
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1
您将1
传递给test
。在测试中,您修改了局部变量x
。 a
未更改且无法以此方式更改 - 我们传递a
的值而不是a
的引用。
(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)
您将列表(1)
传递给测试。该列表未复制。局部变量x
指向列表中的第一个cons单元格。然后,将第一个cons单元的 car 修改为2.由于未复制列表,因此修改传递的列表。 a
也指向该列表的第一个cons单元格。所以它也是(2)
。
答案 1 :(得分:3)
如果您不想修改任何内容,请不要使用incf
。使用1+
。使用incf
的唯一原因是因为你想要它的副作用。
至于为什么会发生这种情况,在传递给函数之前会对参数进行求值。当test
与a
为1时调用a
时,您传递的值为1,无法修改。当setf
解析为列表时,如果您选择使用破坏性功能,则会传递一个列表,该列表可以在整个商店中{{1}}。
答案 2 :(得分:2)
请参阅nth上的文档。 nth
会返回setq
可以继续操作的地方。
nth可用于指定setf的位置。特别, (setf(nth n list)new-object)==(setf(car(nthcdr n list))new-object)