2

我在使用访问器函数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),为什么它被修改了?我还尝试了其他功能,例如carfirst,结果是一样的。

PS,我在 Lispworks 和 SBCL 中试过,结果一样。

4

3 回答 3

4
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1

1传给test. 在 test 中,您修改了局部变量xa没有改变,也不能那样改变——我们传递的值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)

于 2012-12-24T10:11:53.177 回答
3

如果您不想修改任何内容,请不要使用incf. 使用1+. 使用的唯一原因incf是因为你想要它的副作用。

至于为什么会发生这种情况,参数在传递给函数之前会被评估。当您testa1 调用时,您传递的值是 1,该值无法修改。解析为列表时a,您传递的是一个列表,setf如果您选择使用破坏性功能,则可以在整个商店中使用。

于 2012-12-24T10:19:07.530 回答
2

请参阅有关nth的文档。 nth返回一个setq可以操作的地方。

nth 可用于指定 setf 的位置。具体来说, (setf (nth n list) new-object) == (setf (car (nthcdr n list)) new-object)

于 2012-12-24T09:45:23.780 回答