在Common Lisp中将函数应用于函数参数时,函数第n次访问哪个对象?
我在使用存取器函数时遇到一些问题。我将列表传递给某个函数,并使用nth对函数中的列表元素进行新绑定,然后当我从函数中调用列表时,它会被修改,这不是我想要的!会发生什么 一些例子在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)))
(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,结果是一样的
另外,我在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)