在Common Lisp中将函数应用于函数参数时,函数第n次访问哪个对象?

在Common Lisp中将函数应用于函数参数时,函数第n次访问哪个对象?,lisp,common-lisp,Lisp,Common Lisp,我在使用存取器函数时遇到一些问题。我将列表传递给某个函数,并使用nth对函数中的列表元素进行新绑定,然后当我从函数中调用列表时,它会被修改,这不是我想要的!会发生什么 一些例子 (defun test (x) (incf x)) => TEST (setq a 1) => 1 (test a) => 2 a => 1 我知道上面发生了什么,但如果我们把所有的事情都改成列表,就会发生一些我无法理解的事情 (defun test (x) (incf (nth 0 x)))

我在使用存取器函数时遇到一些问题。我将列表传递给某个函数,并使用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,结果是一样的

另外,我在Lispworks和SBCL中试用了它,结果相同。

请参阅上的文档
nth
返回一个
setq
可以在其上操作的位置

n可用于指定要设置的位置。明确地 (setf(第n个列表)新对象)==(setf(汽车(第n个列表))新对象)

您将
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)

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


至于发生这种情况的原因,参数在传递给函数之前会进行求值。当调用
test
a
为1时,将传递值1,该值不能修改。当
a
解析为一个列表时,您正在传递一个列表,如果您选择使用破坏性函数,该列表可以
setf
'd遍布整个商店

谢谢,我已经读过了。似乎我已经找到了原因-列表在CL中是通过引用传递的,所以这就是为什么原始列表被修改的原因。不,列表不是通过引用传递的。它们和其他事物一样,是通过价值传递的。只是列表的值恰好是一个引用。这是一个很大的不同。谢谢!这不是处理列表的实用方法。。。如果我想让一切都“功能化”,我必须形成一个新的列表,如
(list(1+(nth 0 x)))
(不是特别正确,但想法很清楚),对吗?@TheEnt:Common Lisp从不复制列表、数组、流、条件、CLOS对象、结构等数据结构。大多数口齿不清不会这样做。
(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)